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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Ryo Nakamura
December 20, 2018
Programming
120
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
楽しい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
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
150
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
160
CSC307 Lecture 17
javiergs
PRO
0
320
Modding RubyKaigi for Myself
yui_knk
0
920
Oxcを導入して開発体験が向上した話
yug1224
4
310
The NotImplementedError Problem in Ruby
koic
1
710
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
690
Webフレームワークの ベンチマークについて
yusukebe
0
160
技術記事、 専門家としてのプログラマ、 言語化
mizchi
4
2.8k
AIで効率化できた業務・日常
ochtum
0
120
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2k
Featured
See All Featured
Designing Experiences People Love
moore
143
24k
A designer walks into a library…
pauljervisheath
211
24k
Test your architecture with Archunit
thirion
1
2.3k
Writing Fast Ruby
sferik
630
63k
ラッコキーワード サービス紹介資料
rakko
1
3.6M
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
Code Review Best Practice
trishagee
74
20k
Faster Mobile Websites
deanohume
310
31k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
720
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
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 Έ͍ͨͳ ͕ͭඞཁͳͱ͖
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠