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
Decorating JavaScript - source{d} edition
Search
Sergio Arbeo
June 24, 2017
Programming
1
150
Decorating JavaScript - source{d} edition
An introduction to Class and property decorators, Stage 2, proposal.
Sergio Arbeo
June 24, 2017
Tweet
Share
More Decks by Sergio Arbeo
See All by Sergio Arbeo
Testing sin Dogmas
serabe
0
240
Componentes: DD
serabe
0
380
Introducción a JSONAPI
serabe
1
190
Bienvenidos a Ember Madrid
serabe
2
220
Lo que la cafeína le hizo a JS
serabe
1
230
Lo que la cafeína le hizo a JS
serabe
1
3k
Taller de Introducción a Ember.JS
serabe
1
210
Generadores en JavaScript
serabe
1
520
El diablo está en los detalles
serabe
0
680
Other Decks in Programming
See All in Programming
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
1
2.5k
CSC307 Lecture 07
javiergs
PRO
0
550
15年続くIoTサービスのSREエンジニアが挑む分散トレーシング導入
melonps
2
190
Fragmented Architectures
denyspoltorak
0
150
カスタマーサクセス業務を変革したヘルススコアの実現と学び
_hummer0724
0
680
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
450
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
AI時代の認知負荷との向き合い方
optfit
0
150
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.5k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
1.8k
Implementation Patterns
denyspoltorak
0
280
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
300
Featured
See All Featured
Utilizing Notion as your number one productivity tool
mfonobong
3
220
ラッコキーワード サービス紹介資料
rakko
1
2.2M
Agile that works and the tools we love
rasmusluckow
331
21k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
140
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
110
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Thoughts on Productivity
jonyablonski
74
5k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
GraphQLの誤解/rethinking-graphql
sonatard
74
11k
How Software Deployment tools have changed in the past 20 years
geshan
0
32k
Transcript
Decorating JavaScript Sergio Arbeo Serabe Serabe
History
History • Early work from March, 2015 • Stage 2
for 11 months • PR for babylon merged 2 days ago.
What is a decorator?
What is a decorator? New Syntax
What is a decorator? import Evented from 'evented'; import {
mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
What is a decorator? import Evented from 'evented'; import {
mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
What is a decorator? import Evented from 'evented'; import {
mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
Syntax Valid @foo @foo(…args) @foo.bar @foo.bar(…args) @foo.bar.baz @foo.bar.baz(…args)
Syntax Valid @foo @foo(…args) @foo.bar @foo.bar(…args) @foo.bar.baz @foo.bar.baz(…args) Invalid @foo[bar]
@foo[bar](…args) @foo(…args).bar @foo(…args).bar(…args) @foo.bar(…args).baz @foo.bar(…args).baz(…args)
How can I implement one?
How to implement one? ClassDecorator: (Constructor, ParentClass, MemberDescriptor[]) : void
How to implement one? MemberDecorator: (MemberDescriptor) : MemberDescriptor
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:
boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
Property Descriptor type PropertyDescriptor = DataDescriptor | AccessorDescriptor;
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface DataDescriptor { configurable?: boolean; enumerable?: boolean; value?:
any; writable?: boolean; }
Property Descriptor interface AccessorDescriptor { configurable?: boolean; enumerable?: boolean; get?():
any; set?(v: any): void; }
Property Descriptor interface AccessorDescriptor { configurable?: boolean; enumerable?: boolean; get?():
any; set?(v: any): void; }
Property Descriptor interface AccessorDescriptor { configurable?: boolean; enumerable?: boolean; get?():
any; set?(v: any): void; }
Property Descriptor interface AccessorDescriptor { configurable?: boolean; enumerable?: boolean; get?():
any; set?(v: any): void; }
Property Descriptor interface AccessorDescriptor { configurable?: boolean; enumerable?: boolean; get?():
any; set?(v: any): void; }
Property Descriptor type PropertyDescriptor = DataDescriptor | AccessorDescriptor;
How can I implement one?
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function validator(predicate) { return function(memberDescriptor) { let {
descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateData(descriptor, predicate) { let { value }
= descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
Simple validator function decorateAccessor(descriptor, predicate) { let { set }
= descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
Simple validator function decorateAccessor(descriptor, predicate) { let { set }
= descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
Simple validator function decorateAccessor(descriptor, predicate) { let { set }
= descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
Simple validator function decorateAccessor(descriptor, predicate) { let { set }
= descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
Simple validator function decorateAccessor(descriptor, predicate) { let { set }
= descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; }
Gotchas
Evaluation / Execution
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; }
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Evaluation
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Evaluation
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Execution
Simple validator const isString = validator( value => typeof value
=== 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Execution
Simple validator isString( validator(el => el === '1234')( passwordMemberDescriptor )
)
setters / getters
setters / getters class MyClass { @duplicate get hola() {
return 'hola'; } @map( x => x.toLowerCase() ) set hola(x) { send(x); } }
setters / getters class MyClass { @duplicateGetter @mapSetter( x =>
x.toLowerCase() ) get hola() { return 'hola'; } set hola(x) { send(x); } }
setters / getters class MyClass { get hola() { return
'hola'; } @duplicateGetter @mapSetter( x => x.toLowerCase() ) set hola(x) { send(x); } }
Cool Things that Can Be Done
Classics • Read Only properties • Validations • Computed Properties
• Memoized methods • Autobinding • Better Singleton Classes • Conversion setters and getters • Deprecate methods • Debounce • Throttle • Map returned value
Different express API @express('/posts') class Posts { @get index(req, res)
{ } @authorized @post create(req, res) { } @get(':id') show(req, res) { } }
@I18ned class Operations { @i18nMethod('operations.sum') static sum(...args) { return args.reduce((a,
b) => a+b, 0); } } Operations.sum(1, 2) // 3 Operations.suma(2, 3) // 5 Operations.batuketa(2, 3) // 5 I18ned API
Any questions? Sergio Arbeo Serabe Serabe
Thank you! Sergio Arbeo Serabe Serabe