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
Ryo Nakamura
December 20, 2018
Programming
2
120
楽しいProxy
Proxy is so much fun! @We are JavaScripters! #27
Ryo Nakamura
December 20, 2018
Tweet
Share
More Decks by Ryo Nakamura
See All by Ryo Nakamura
やさしい仮想DOM
ryonkmr
1
230
Other Decks in Programming
See All in Programming
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
510
副作用をどこに置くか問題:オブジェクト指向で整理する設計判断ツリー
koxya
1
600
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
450
Data-Centric Kaggle
isax1015
2
770
Patterns of Patterns
denyspoltorak
0
1.4k
Architectural Extensions
denyspoltorak
0
280
AI巻き込み型コードレビューのススメ
nealle
1
150
0→1 フロントエンド開発 Tips🚀 #レバテックMeetup
bengo4com
0
560
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
1.8k
生成AIを使ったコードレビューで定性的に品質カバー
chiilog
1
260
組織で育むオブザーバビリティ
ryota_hnk
0
170
CSC307 Lecture 07
javiergs
PRO
0
550
Featured
See All Featured
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
96
Between Models and Reality
mayunak
1
180
The Curse of the Amulet
leimatthew05
1
8.4k
Building Applications with DynamoDB
mza
96
6.9k
Deep Space Network (abreviated)
tonyrice
0
47
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
280
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
0
170
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
430
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
410
KATA
mclloyd
PRO
34
15k
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 Έ͍ͨͳ ͕ͭඞཁͳͱ͖
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠