Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
楽しいProxy
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Ryo Nakamura
December 20, 2018
Programming
120
2
Share
楽しいProxy
Proxy is so much fun! @We are JavaScripters! #27
Ryo Nakamura
December 20, 2018
More Decks by Ryo Nakamura
See All by Ryo Nakamura
やさしい仮想DOM
ryonkmr
1
240
Other Decks in Programming
See All in Programming
ハーネスエンジニアリングにどう向き合うか 〜ルールファイルを超えて開発プロセスを設計する〜 / How to approach harness engineering
rkaga
22
13k
Claude Code × Gemini × Ebitengine ゲーム制作素人WebエンジニアがGoでゲームを作った話
webzawa
0
140
書籍「ユーザーストーリーマッピング」が私のバイブル
asumikam
3
350
PHP で mp3 プレイヤーを実装しよう
m3m0r7
PRO
0
280
Coding at the Speed of Thought: The New Era of Symfony Docker
dunglas
0
5k
Oxlintとeslint-plugin-react-hooks 明日から始められそう?
t6adev
0
270
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
3
270
感情を設計する
ichimichi
5
1.5k
forteeの改修から振り返るPHPerKaigi 2026
muno92
PRO
3
290
[RubyKaigi 2026] Require Hooks
palkan
1
200
CDK Deployのための ”反響定位”
watany
4
770
Swift Concurrency Type System
inamiy
0
530
Featured
See All Featured
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
500
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
Fireside Chat
paigeccino
42
3.9k
Amusing Abliteration
ianozsvald
1
150
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.7k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
510
The Spectacular Lies of Maps
axbom
PRO
1
700
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
170
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
Transcript
RyoNkmr PROJECT DATE PRESENTER 2018-12-20 ָ͍͠Proxy @WE ARE JAVASCRIPTERS! #27
ࣗݾհ • RyoNkmr • @RyoNkmr_ • Retty Inc. • JavaScript
3ੜ • ॳొஃ
ָ͍͠ Proxy
Proxy
...͜ΕΒجຊతͳݴޠૢ࡞ʢྫ ͑ɺϓϩύςΟݕࡧɺೖɺྻ ڍɺؔݺͼग़͠ͳͲʣʹׂΓࠐ Έɺಈ࡞ΛΧελϚΠζͰ͖·͢ɻ [ϝλϓϩάϥϛϯά | MDN](https:// developer.mozilla.org/ja/docs/Web/ JavaScript/Guide/ Meta_programming)
Proxy
ରԠঢ়گ
https://caniuse.com/#search=proxy
https://node.green/#ES2015-built-ins-Proxy
Browser: IE11Ҏ֎ Node: v6.4.0Ҏ߱ ରԠঢ়گ
Proxyͱͷग़ձ͍
ͱ͋Δݱͷ Pull Request { type: Array, validate(values) { return values.length
!== 0; }, }
(ϨϏϡΞʔ) { type: Array, validate(values) { return values.length !== 0;
}, } const fakeData = { length : 1000 }; ͜ΕͰಥഁͰ͖ΔͷͰɾɾɾʁ(Request Changes)
{ type: Array, validate(values) { return Array.isArray(values) && values.length !==
0; }, }
(ϨϏϡΞʔ) { type: Array, validate(values) { return Array.isArray(values) &&
values.length !== 0; }, }
(ϨϏϡΞʔ) const fakeData = new Proxy([], { get(...args) { if
(args[1] === 'length') { return -100000000000; } return Reflect.get(...args); } }); > fakeData.length // -100000000000 > Array.isArray(fakeData) // true ͜ΕͰಥഁͰ͖ΔͷͰɾɾɾʁ(Request Changes) { type: Array, validate(values) { return Array.isArray(values) && values.length !== 0; }, }
{ type: Array, validate(values) { return Array.isArray(values) && values.length >
0; }, }
Proxy
͓ͪΌͰɾɾɾʁ
None
͍ಓΛߟ͑ͯΈΔ
ॲཧΛࠩ͠ࠐΉ
Logger on a Node.js Application
module.exports = new Proxy(console, { get(target, prop, receiver) { return
(...args) => { require('fs').appendFile('logger.log', `[${prop}]: ${args}`, 'utf8', err => { if (err) { throw err; } }); return Reflect.apply(target[prop], receiver, args); }; } }); console Λ Proxy
> const logger = require('./log.js'); > logger.log('plz log me') plz
log me > logger.error('this is an error!') this is an error! > logger.count('cat') cat: 1 > logger.count('dog') dog: 1 > logger.count('cat') cat: 2 console ͱಉ͡ interface
$ cat logger.log [log]: plz log me [error]: this is
an error! [count]: cat [count]: dog [count]: cat ࣮ߦ࣌ʹϑΝΠϧʹॻ͖ग़͢
Get Λ Proxy ͯ͠༡Ϳ
ແݶϝιουνΣʔϯ > https://www.keithcirkel.co.uk/metaprogramming-in-es6- part-3-proxies/
module.exports = (domain = 'google.com') => { let paths =
[]; // ঢ়ଶΛ͓࣋ͬͯ͘ // ঢ়ଶΛݩʹURLจࣈྻΛΈཱͯΔؔͷఆٛ const buildUrl = () => { const _paths = [...paths]; paths = []; return `https://${domain}/${_paths.join('/')}`; }; return new Proxy(buildUrl, { get(_, prop, receiver) { // propertyΞΫηεΛঢ়ଶͷมߋʹ͏ paths = [...paths, prop]; // chaining͢ΔͨΊʹProxyࣗΛฦͯ͋͛͠Δ return receiver; }, }); };
const urlBuilder = require('./urlBuilder.js'); const google = urlBuilder('www.google.co.jp'); > google.image.saikyo.engineer.wannabe();
'https://www.google.co.jp/image/saikyo/engineer/wannabe' > google.search.cool.javascripters(); 'https://www.google.co.jp/search/cool/javascripters' method missing Ά͍͜ͱ͕Ͱ͖Δ
Array Λ Proxy ͯ͠༡Ϳ
Πέϝϯͳ Array
const parsePropName = prefixCool => { const [, name] =
/^cool(\w+)/.exec(prefixCool) || [, null]; return name !== null ? `${name[0].toLowerCase()}${name.slice(1)}` : prefixCool; } module.exports = ({ goodLooking } = { goodLooking: false }) => ( new Proxy([], { get(target, prop, receiver) { const actualPropName = parsePropName(prop); if ( typeof target[actualPropName] !== 'function' || goodLooking || prop.startsWith('cool') ) { return Reflect.get(target, actualPropName, receiver); } throw new TypeError(`Hmm... You'are not my type`); } }) );
> const coolArray = require('./coolArray.js')(); undefined > coolArray.push('hey, man.'); TypeError:
Hmm... You'are not my type at Object.get (.../proxy/coolArray.js:18:13) > coolArray.coolPush('hey, handsome man.'); 1 > [...coolArray.coolValues()]; [ 'hey, handsome man.' ] cool͍͍ͬͯͪͪݴΘͳ͍ͱ ݴ͏͜ͱΛฉ͔ͳ͍ArrayΛ࡞ΕΔ
Proxy ָ͍͠
·ͱΊ
• ґଘίʔυΛͦͷ··ʹɺґଘϥΠϒϥ ϦΛࣅͨΑ͏ͳผʹࠩ͠ସ͑Δͱ͖ • ϥΠϒϥϦͱ͔ϑϨʔϜϫʔΫͭ͘Δͱ ͖ • Array.isArray ͕ true
Λฦ͢ͷʹ length ͩ ͚͓͔͍͠Λฦ͢ Array Έ͍ͨͳ ͕ͭඞཁͳͱ͖
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠