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
130
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
220
Componentes: DD
serabe
0
340
Introducción a JSONAPI
serabe
1
170
Bienvenidos a Ember Madrid
serabe
2
210
Lo que la cafeína le hizo a JS
serabe
1
220
Lo que la cafeína le hizo a JS
serabe
1
3k
Taller de Introducción a Ember.JS
serabe
1
190
Generadores en JavaScript
serabe
1
510
El diablo está en los detalles
serabe
0
610
Other Decks in Programming
See All in Programming
202507_ADKで始めるエージェント開発の基本 〜デモを通じて紹介〜(奥田りさ)The Basics of Agent Development with ADK — A Demo-Focused Introduction
risatube
PRO
6
1.3k
構造化・自動化・ガードレール - Vibe Coding実践記 -
tonegawa07
0
170
LLMは麻雀を知らなすぎるから俺が教育してやる
po3rin
3
1.8k
Android 15以上でPDFのテキスト検索を爆速開発!
tonionagauzzi
0
180
テスターからテストエンジニアへ ~新米テストエンジニアが歩んだ9ヶ月振り返り~
non0113
2
250
11年かかって やっとVibe Codingに 時代が追いつきましたね
yimajo
1
230
DynamoDBは怖くない!〜テーブル設計の勘所とテスト戦略〜
hyamazaki
0
160
Comparing decimals in Swift Testing
417_72ki
0
160
Vibe coding コードレビュー
kinopeee
0
390
TypeScriptでDXを上げろ! Hono編
yusukebe
4
920
Amazon Q CLI開発で学んだAIコーディングツールの使い方
licux
3
160
抽象化という思考のツール - 理解と活用 - / Abstraction-as-a-Tool-for-Thinking
shin1x1
1
910
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Bash Introduction
62gerente
613
210k
Writing Fast Ruby
sferik
628
62k
Rebuilding a faster, lazier Slack
samanthasiow
83
9.1k
Being A Developer After 40
akosma
90
590k
KATA
mclloyd
31
14k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Testing 201, or: Great Expectations
jmmastey
44
7.6k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
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