Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Decorating JavaScript - source{d} edition
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Sergio Arbeo
June 24, 2017
Programming
170
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Decorating JavaScript - source{d} edition
An introduction to Class and property decorators, Stage 2, proposal.
Sergio Arbeo
June 24, 2017
More Decks by Sergio Arbeo
See All by Sergio Arbeo
Testing sin Dogmas
serabe
0
270
Componentes: DD
serabe
0
400
Introducción a JSONAPI
serabe
1
220
Bienvenidos a Ember Madrid
serabe
2
240
Lo que la cafeína le hizo a JS
serabe
1
260
Lo que la cafeína le hizo a JS
serabe
1
3k
Taller de Introducción a Ember.JS
serabe
1
220
Generadores en JavaScript
serabe
1
540
El diablo está en los detalles
serabe
0
710
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
560
SREの越境 / SRE Collaboration
y0hgi
2
300
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
470
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
7.7k
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
260
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
630
mrbgem 三角測量 開発
ogom
0
210
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
150
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
140
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
360
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
480
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
210
Featured
See All Featured
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Embracing the Ebb and Flow
colly
88
5.2k
エンジニアに許された特別な時間の終わり
watany
109
250k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Scaling GitHub
holman
464
140k
Tell your own story through comics
letsgokoyo
1
1.1k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
350
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
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