SlideShare a Scribd company logo
Metaprogramming in
JavaScript
Web Directions Summit | November 17
Hello!
I am Mehdi Valikhani
Software Engineer at Autopilot
Metaprogramming?!
“Metaprogramming is a programming technique in
which computer programs have the ability to treat
programs as their data. It means that a program can
be designed to read, generate, analyse or transform
other programs or itself while running
source: Wikipedia
“Metaprogramming is a programming technique in
which computer programs have the ability to treat
programs as their data. It means that a program can
be designed to read, generate, analyse or transform
other programs or itself while running
source: Wikipedia
Reflection
“In computer science,reflection is the ability of a
computer program to examine,introspect, and modify
its own structure and behaviour at runtime. Reflection
is a valuable language feature and it facilitates
metaprogramming.
source: Wikipedia
Language features that enables
reflection
1.
Evaluate a string as if it
were a source code
statement at runtime.
2.
Convert a string matching
the symbolic name of a class
or function into a reference
to or invocation of that class
or function.
3.
Discover and modify source
code constructions (such as
code blocks, classes,
methods, protocols, etc.) as
first-class objects at
runtime.
source: Wikipedia
Reflective JavaScript
Metaprogramming
Reflective
JavaScript
Metaprogramming
Using ES5 features
Metaprogramming features of ES5
Code Evaluation
eval()
Examination
➔ instanceof
➔ typeof
➔ Object.getOwnPropertyNames()
Modification
Getter, setter
Reflective
JavaScript
Metaprogramming
Using ES6 features
Symbol ReflectProxy
Symbols
The new type in JavaScript
➔ The seventh type of values in JavaScript
Symbol
➔ The Symbol() function returns a value of type symbol
➔ Symbol() always returns unique values
➔ They may be used as an identifier for object properties
source: MDN
Example: Using Symbol as property identifier
const nameField = Symbol('beer name');
const beer = {
[nameField]: 'VB!'
};
console.log(beer[nameField]); // -> VB!
Example: Using Symbol as property identifier
const nameField = Symbol('beer name');
const beer = {
[nameField]: 'VB!'
};
console.log(beer[nameField]); // -> VB!
Example: Using Symbol as property identifier
const nameField = Symbol('beer name');
const beer = {
[nameField]: 'VB!'
};
console.log(beer[nameField]); // -> VB!
Example: Using Symbol as property identifier
const nameField = Symbol('beer name');
const beer = {
[nameField]: 'VB!'
};
console.log(beer[nameField]); // -> VB!
Well-known
Symbols
➔ A set of built-in JavaScript symbols
➔ Represent internal language behaviours
➔ They were not exposed to developers before
source: MDN
Symbols are used by ES6 to enable
“Reflection within implementation”.
Developers include them on their existing
classes and objects to change the default
behaviour of an operation or action.
source: keithcirkel.co.uk
What can be done using well-known symbols
➔ Control the behaviour of instanceof for an implemented class
➔ Manipulate the behaviour of for of when iterated over a class
➔ Control over Array.concat
➔ Custom matches for String.match(), String.replace(),
String.search() and String.split()
➔ Control the behaviour of Javascript when converting objects
to primitive types
Check MDN for a list of well-known symbols
Example: Using well-known Symbol.hasInstance to modify behaviour of “instanceof”
class MyArray {
}
const friends = ['foo', 'bar'];
console.log(friends instanceof MyArray); // -> false
class MyArray {
static [Symbol.hasInstance](object) {
return Array.isArray(object);
}
}
const friends = ['foo', 'bar'];
console.log(friends instanceof MyArray); // -> true
Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class
class ShoppingBasket {
constructor() {
this.items = [];
}
add(title, quantity, price) {
this.items.push({ title, quantity, price});
}
total() {
return this.items.reduce(function(accumulator, item) {
return accumulator + (item.price * item.quantity);
}, 0);
}
}
}
const basket = new ShoppingBasket();
basket.add('bread', 2, 2.5);
basket.add('milk', 1, 1.4);
Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class
class ShoppingBasket {
constructor() {
this.items = [];
}
add(title, quantity, price) {
this.items.push({ title, quantity, price});
}
total() {
return this.items.reduce(function(accumulator, item) {
return accumulator + (item.price * item.quantity);
}, 0);
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') return this.total();
return this;
}
}
const basket = new ShoppingBasket();
basket.add('bread', 2, 2.5);
basket.add('milk', 1, 1.4);
console.log(+basket); // -> 6.4
console.log(new Number(basket)); // -> 6.4
Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class
class ShoppingBasket {
constructor() {
this.items = [];
}
add(title, quantity, price) {
this.items.push({ title, quantity, price});
}
total() {
return this.items.reduce(function(accumulator, item) {
return accumulator + (item.price * item.quantity);
}, 0);
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') return this.total();
return this;
}
}
const basket = new ShoppingBasket();
basket.add('bread', 2, 2.5);
basket.add('milk', 1, 1.4);
console.log(+basket); // -> 6.4
console.log(new Number(basket)); // -> 6.4
Proxy
Proxy, as the name indicates, provides
“Reflection through interception”.
It wraps objects and intercepts their
behaviours through traps.
source: keithcirkel.co.uk
What can be done using Proxy
➔ A trap for delete operator
➔ Manipulate the behaviour of in operator
➔ Control over getting and setting property values
➔ A trap for function calls
➔ A trap for new operator
Check MDN for a list of Proxy features
Example: Implementation of a virtual field using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
get: function(object, fieldName) {
if (fieldName === 'fullName') {
return `${object.firstName} ${object.lastName}`;
}
return object[fieldName];
}
};
const proxiedStudent = new Proxy(student, studentProxy);
console.log(proxiedStudent.fullName); // -> Jackson Rowe
Example: Implementation of a virtual field using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
get: function(object, fieldName) {
if (fieldName === 'fullName') {
return `${object.firstName} ${object.lastName}`;
}
return object[fieldName];
}
};
const proxiedStudent = new Proxy(student, studentProxy);
console.log(proxiedStudent.fullName); // -> Jackson Rowe
Example: Implementation of a virtual field using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
get: function(object, fieldName) {
if (fieldName === 'fullName') {
return `${object.firstName} ${object.lastName}`;
}
return object[fieldName];
}
};
const proxiedStudent = new Proxy(student, studentProxy);
console.log(proxiedStudent.fullName); // -> Jackson Rowe
Example: Implementation of a virtual field using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
get: function(object, fieldName) {
if (fieldName === 'fullName') {
return `${object.firstName} ${object.lastName}`;
}
return object[fieldName];
}
};
const proxiedStudent = new Proxy(student, studentProxy);
console.log(proxiedStudent.fullName); // -> Jackson Rowe
Example: Value validation using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
set: function(object, fieldName, value) {
// validation logic for the “age” field
if (fieldName === 'age') {
if (typeof value !== 'number') {
throw TypeError('only numbers are accepted');
}
if (value <= 0) throw TypeError('that is impossible');
}
object[fieldName] = value;
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
proxiedStudent.age = 'a'; // errors
proxiedStudent.age = -1; // errors
proxiedStudent.age = 12; // does not error
Example: Value validation using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
set: function(object, fieldName, value) {
// validation logic for the “age” field
if (fieldName === 'age') {
if (typeof value !== 'number') {
throw TypeError('only numbers are accepted');
}
if (value <= 0) throw TypeError('that is impossible');
}
object[fieldName] = value;
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
proxiedStudent.age = 'a'; // errors
proxiedStudent.age = -1; // errors
proxiedStudent.age = 12; // does not error
Example: Value validation using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
set: function(object, fieldName, value) {
// validation logic for the “age” field
if (fieldName === 'age') {
if (typeof value !== 'number') {
throw TypeError('only numbers are accepted');
}
if (value <= 0) throw TypeError('that is impossible');
}
object[fieldName] = value;
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
proxiedStudent.age = 'a'; // errors
proxiedStudent.age = -1; // errors
proxiedStudent.age = 12; // does not error
Example: Value validation using Proxy
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
set: function(object, fieldName, value) {
// validation logic for the “age” field
if (fieldName === 'age') {
if (typeof value !== 'number') {
throw TypeError('only numbers are accepted');
}
if (value <= 0) throw TypeError('that is impossible');
}
object[fieldName] = value;
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
proxiedStudent.age = 'a'; // errors
proxiedStudent.age = -1; // errors
proxiedStudent.age = 12; // does not error
Example: Protect “id” field from deletion using a Proxy
const student = {
id: 'jackson-rowe',
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
deleteProperty: function(object, fieldName) {
if (fieldName === 'id') return false;
delete object[fieldName];
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
delete proxiedStudent.id // -> false
console.log(proxiedStudent.id); // jackson-rowe
Example: Protect “id” field from deletion using a Proxy
const student = {
id: 'jackson-rowe',
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
deleteProperty: function(object, fieldName) {
if (fieldName === 'id') return false;
delete object[fieldName];
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
delete proxiedStudent.id // -> false
console.log(proxiedStudent.id); // jackson-rowe
Example: Protect “id” field from deletion using a Proxy
const student = {
id: 'jackson-rowe',
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
deleteProperty: function(object, fieldName) {
if (fieldName === 'id') return false;
delete object[fieldName];
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
delete proxiedStudent.id // -> false
console.log(proxiedStudent.id); // jackson-rowe
Example: Protect “id” field from deletion using a Proxy
const student = {
id: 'jackson-rowe',
firstName: 'Jackson',
lastName: 'Rowe',
};
const studentProxy = {
deleteProperty: function(object, fieldName) {
if (fieldName === 'id') return false;
delete object[fieldName];
return true;
}
};
const proxiedStudent = new Proxy(student, studentProxy);
delete proxiedStudent.id // -> false
console.log(proxiedStudent.id); // jackson-rowe
Reflect
JavaScript’s new built-in object
Reflect is all about “Reflection through
introspection” - provides API to discover very
low level information about code.
source: keithcirkel.co.uk
What can be done using Reflect
➔ Call a function using Reflect.apply()
➔ Define a property using Reflect.defineProperty()
➔ Delete a property using Control over Reflect.deleteProperty()
➔ Get a property value using Reflect.get()
➔ Set property value using Reflect.set()
➔ Check if a property exist using Reflect.has()
Check MDN for a list of Reflect features
What Reflect object offers are either a
newer versions of existing methods or
entirely new methods - allowing new levels
of Reflection within JavaScript.
source: keithcirkel.co.uk
Example: Deleting a property using Reflect.deleteProperty()
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
console.log(student.firstName); // -> Jackson
Reflect.deleteProperty(student, 'firstName');
console.log(student.firstName); // -> undefined
Example: Deleting a property using Reflect.deleteProperty()
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
console.log(student.firstName); // -> Jackson
Reflect.deleteProperty(student, 'firstName');
console.log(student.firstName); // -> undefined
Example: Deleting a property using Reflect.deleteProperty()
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
console.log(student.firstName); // -> Jackson
Reflect.deleteProperty(student, 'firstName');
console.log(student.firstName); // -> undefined
Example: Deleting a property using Reflect.deleteProperty()
const student = {
firstName: 'Jackson',
lastName: 'Rowe',
};
console.log(student.firstName); // -> Jackson
Reflect.deleteProperty(student, 'firstName');
console.log(student.firstName); // -> undefined
100%Modern Browsers (Edge, Firefox, Safari, Chrome)
0%IE 11
100%Node 8
source: http://kangax.github.io/compat-table/es6/
Native support
Resources
● Wikipedia - Metaprogramming
● Wikipedia - Reflection in Computer Science
● Mozilla - Metaprogramming
● Metaprogramming in ES6 by Keith Cirkel
Credits
Special thanks to all the people who made and
released these awesome resources for free:
▷ MDN web docs
▷ Wikipedia and the contributors
▷ Keith Cirkel for the Metaprogramming series
▷ Presentation template by SlidesCarnival
Thanks!
Any questions?
You can find me at:
➔ @mehdivk
➔ linkedin.com/in/valikhani/
➔ hi@mv.id.au

More Related Content

ODP
Javascript
PDF
JavaScript Basics and Best Practices - CC FE & UX
PDF
Java Script Best Practices
PPTX
Java script
PDF
Advanced javascript
PPTX
From C++ to Objective-C
PDF
Fundamental JavaScript [UTC, March 2014]
PPTX
JavaScript Fundamentals & JQuery
Javascript
JavaScript Basics and Best Practices - CC FE & UX
Java Script Best Practices
Java script
Advanced javascript
From C++ to Objective-C
Fundamental JavaScript [UTC, March 2014]
JavaScript Fundamentals & JQuery

What's hot (20)

PDF
Bottom Up
PDF
Singletons in PHP - Why they are bad and how you can eliminate them from your...
PDF
Powerful JavaScript Tips and Best Practices
PPTX
Javascript basics for automation testing
PDF
Ten useful JavaScript tips & best practices
PPT
Java script
PPTX
Javascript 101
PDF
JavaScript 101
PPTX
JavaScript in Object-Oriented Way
PDF
A Re-Introduction to JavaScript
PPTX
Intro to Javascript
PDF
Basics of JavaScript
PPTX
Lab #2: Introduction to Javascript
PPT
JavaScript Tutorial
PPT
Advanced Javascript
PDF
Object Oriented Programming in JavaScript
KEY
Javascript tid-bits
PPT
Java script -23jan2015
PPTX
Object Oriented Programming In JavaScript
PPT
JavaScript Basics
Bottom Up
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Powerful JavaScript Tips and Best Practices
Javascript basics for automation testing
Ten useful JavaScript tips & best practices
Java script
Javascript 101
JavaScript 101
JavaScript in Object-Oriented Way
A Re-Introduction to JavaScript
Intro to Javascript
Basics of JavaScript
Lab #2: Introduction to Javascript
JavaScript Tutorial
Advanced Javascript
Object Oriented Programming in JavaScript
Javascript tid-bits
Java script -23jan2015
Object Oriented Programming In JavaScript
JavaScript Basics
Ad

Similar to Metaprogramming in JavaScript (20)

PPT
Introduction to Javascript
PPT
Reversing JavaScript
PPT
JavaScript Misunderstood
PPTX
Javascriptinobject orientedway-090512225827-phpapp02
KEY
PDF
JavaScript - Chapter 8 - Objects
PDF
Javascript
PDF
HSC INFORMATION TECHNOLOGY CHAPTER 3 ADVANCED JAVASCRIPT
PDF
ES6 metaprogramming unleashed
PPTX
11. session 11 functions and objects
PPTX
Web Host_G4.pptx
PPTX
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
PPT
A Deeper look into Javascript Basics
PPTX
JavaScript Basics - GameCraft Training
PPT
Backbone js
PPTX
JavaScript (without DOM)
PPT
Oop Constructor Destructors Constructor Overloading lecture 2
PPT
Ajax and JavaScript Bootcamp
PDF
Angular JS2 Training Session #1
Introduction to Javascript
Reversing JavaScript
JavaScript Misunderstood
Javascriptinobject orientedway-090512225827-phpapp02
JavaScript - Chapter 8 - Objects
Javascript
HSC INFORMATION TECHNOLOGY CHAPTER 3 ADVANCED JAVASCRIPT
ES6 metaprogramming unleashed
11. session 11 functions and objects
Web Host_G4.pptx
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
A Deeper look into Javascript Basics
JavaScript Basics - GameCraft Training
Backbone js
JavaScript (without DOM)
Oop Constructor Destructors Constructor Overloading lecture 2
Ajax and JavaScript Bootcamp
Angular JS2 Training Session #1
Ad

Recently uploaded (20)

PDF
B.Tech (Electrical Engineering ) 2024 syllabus.pdf
PDF
International Journal of Information Technology Convergence and Services (IJI...
PDF
Queuing formulas to evaluate throughputs and servers
PPTX
meets orient on the new industry intereacting skills .pptx
PDF
Principles of Food Science and Nutritions
PPTX
Practice Questions on recent development part 1.pptx
PPTX
Internship_Presentation_Final engineering.pptx
PDF
flutter Launcher Icons, Splash Screens & Fonts
PPT
SCOPE_~1- technology of green house and poyhouse
PPT
Chapter 6 Design in software Engineeing.ppt
PPTX
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PPTX
TE-AI-Unit VI notes using planning model
PDF
6th International Conference on Artificial Intelligence and Machine Learning ...
PDF
오픈소스 LLM, vLLM으로 Production까지 (Instruct.KR Summer Meetup, 2025)
PPTX
anatomy of limbus and anterior chamber .pptx
PDF
Geotechnical Engineering, Soil mechanics- Soil Testing.pdf
PPTX
The-Looming-Shadow-How-AI-Poses-Dangers-to-Humanity.pptx
PDF
ETO & MEO Certificate of Competency Questions and Answers
PPTX
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx
B.Tech (Electrical Engineering ) 2024 syllabus.pdf
International Journal of Information Technology Convergence and Services (IJI...
Queuing formulas to evaluate throughputs and servers
meets orient on the new industry intereacting skills .pptx
Principles of Food Science and Nutritions
Practice Questions on recent development part 1.pptx
Internship_Presentation_Final engineering.pptx
flutter Launcher Icons, Splash Screens & Fonts
SCOPE_~1- technology of green house and poyhouse
Chapter 6 Design in software Engineeing.ppt
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
TE-AI-Unit VI notes using planning model
6th International Conference on Artificial Intelligence and Machine Learning ...
오픈소스 LLM, vLLM으로 Production까지 (Instruct.KR Summer Meetup, 2025)
anatomy of limbus and anterior chamber .pptx
Geotechnical Engineering, Soil mechanics- Soil Testing.pdf
The-Looming-Shadow-How-AI-Poses-Dangers-to-Humanity.pptx
ETO & MEO Certificate of Competency Questions and Answers
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx

Metaprogramming in JavaScript

  • 2. Hello! I am Mehdi Valikhani Software Engineer at Autopilot
  • 4. “Metaprogramming is a programming technique in which computer programs have the ability to treat programs as their data. It means that a program can be designed to read, generate, analyse or transform other programs or itself while running source: Wikipedia
  • 5. “Metaprogramming is a programming technique in which computer programs have the ability to treat programs as their data. It means that a program can be designed to read, generate, analyse or transform other programs or itself while running source: Wikipedia
  • 7. “In computer science,reflection is the ability of a computer program to examine,introspect, and modify its own structure and behaviour at runtime. Reflection is a valuable language feature and it facilitates metaprogramming. source: Wikipedia
  • 8. Language features that enables reflection 1. Evaluate a string as if it were a source code statement at runtime. 2. Convert a string matching the symbolic name of a class or function into a reference to or invocation of that class or function. 3. Discover and modify source code constructions (such as code blocks, classes, methods, protocols, etc.) as first-class objects at runtime. source: Wikipedia
  • 11. Metaprogramming features of ES5 Code Evaluation eval() Examination ➔ instanceof ➔ typeof ➔ Object.getOwnPropertyNames() Modification Getter, setter
  • 14. Symbols The new type in JavaScript
  • 15. ➔ The seventh type of values in JavaScript Symbol ➔ The Symbol() function returns a value of type symbol ➔ Symbol() always returns unique values ➔ They may be used as an identifier for object properties source: MDN
  • 16. Example: Using Symbol as property identifier const nameField = Symbol('beer name'); const beer = { [nameField]: 'VB!' }; console.log(beer[nameField]); // -> VB!
  • 17. Example: Using Symbol as property identifier const nameField = Symbol('beer name'); const beer = { [nameField]: 'VB!' }; console.log(beer[nameField]); // -> VB!
  • 18. Example: Using Symbol as property identifier const nameField = Symbol('beer name'); const beer = { [nameField]: 'VB!' }; console.log(beer[nameField]); // -> VB!
  • 19. Example: Using Symbol as property identifier const nameField = Symbol('beer name'); const beer = { [nameField]: 'VB!' }; console.log(beer[nameField]); // -> VB!
  • 20. Well-known Symbols ➔ A set of built-in JavaScript symbols ➔ Represent internal language behaviours ➔ They were not exposed to developers before source: MDN
  • 21. Symbols are used by ES6 to enable “Reflection within implementation”. Developers include them on their existing classes and objects to change the default behaviour of an operation or action. source: keithcirkel.co.uk
  • 22. What can be done using well-known symbols ➔ Control the behaviour of instanceof for an implemented class ➔ Manipulate the behaviour of for of when iterated over a class ➔ Control over Array.concat ➔ Custom matches for String.match(), String.replace(), String.search() and String.split() ➔ Control the behaviour of Javascript when converting objects to primitive types Check MDN for a list of well-known symbols
  • 23. Example: Using well-known Symbol.hasInstance to modify behaviour of “instanceof” class MyArray { } const friends = ['foo', 'bar']; console.log(friends instanceof MyArray); // -> false class MyArray { static [Symbol.hasInstance](object) { return Array.isArray(object); } } const friends = ['foo', 'bar']; console.log(friends instanceof MyArray); // -> true
  • 24. Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class class ShoppingBasket { constructor() { this.items = []; } add(title, quantity, price) { this.items.push({ title, quantity, price}); } total() { return this.items.reduce(function(accumulator, item) { return accumulator + (item.price * item.quantity); }, 0); } } } const basket = new ShoppingBasket(); basket.add('bread', 2, 2.5); basket.add('milk', 1, 1.4);
  • 25. Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class class ShoppingBasket { constructor() { this.items = []; } add(title, quantity, price) { this.items.push({ title, quantity, price}); } total() { return this.items.reduce(function(accumulator, item) { return accumulator + (item.price * item.quantity); }, 0); } [Symbol.toPrimitive](hint) { if (hint === 'number') return this.total(); return this; } } const basket = new ShoppingBasket(); basket.add('bread', 2, 2.5); basket.add('milk', 1, 1.4); console.log(+basket); // -> 6.4 console.log(new Number(basket)); // -> 6.4
  • 26. Example: Using well-known Symbol.toPrimitive for a ShoppingBasket class class ShoppingBasket { constructor() { this.items = []; } add(title, quantity, price) { this.items.push({ title, quantity, price}); } total() { return this.items.reduce(function(accumulator, item) { return accumulator + (item.price * item.quantity); }, 0); } [Symbol.toPrimitive](hint) { if (hint === 'number') return this.total(); return this; } } const basket = new ShoppingBasket(); basket.add('bread', 2, 2.5); basket.add('milk', 1, 1.4); console.log(+basket); // -> 6.4 console.log(new Number(basket)); // -> 6.4
  • 27. Proxy
  • 28. Proxy, as the name indicates, provides “Reflection through interception”. It wraps objects and intercepts their behaviours through traps. source: keithcirkel.co.uk
  • 29. What can be done using Proxy ➔ A trap for delete operator ➔ Manipulate the behaviour of in operator ➔ Control over getting and setting property values ➔ A trap for function calls ➔ A trap for new operator Check MDN for a list of Proxy features
  • 30. Example: Implementation of a virtual field using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { get: function(object, fieldName) { if (fieldName === 'fullName') { return `${object.firstName} ${object.lastName}`; } return object[fieldName]; } }; const proxiedStudent = new Proxy(student, studentProxy); console.log(proxiedStudent.fullName); // -> Jackson Rowe
  • 31. Example: Implementation of a virtual field using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { get: function(object, fieldName) { if (fieldName === 'fullName') { return `${object.firstName} ${object.lastName}`; } return object[fieldName]; } }; const proxiedStudent = new Proxy(student, studentProxy); console.log(proxiedStudent.fullName); // -> Jackson Rowe
  • 32. Example: Implementation of a virtual field using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { get: function(object, fieldName) { if (fieldName === 'fullName') { return `${object.firstName} ${object.lastName}`; } return object[fieldName]; } }; const proxiedStudent = new Proxy(student, studentProxy); console.log(proxiedStudent.fullName); // -> Jackson Rowe
  • 33. Example: Implementation of a virtual field using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { get: function(object, fieldName) { if (fieldName === 'fullName') { return `${object.firstName} ${object.lastName}`; } return object[fieldName]; } }; const proxiedStudent = new Proxy(student, studentProxy); console.log(proxiedStudent.fullName); // -> Jackson Rowe
  • 34. Example: Value validation using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { set: function(object, fieldName, value) { // validation logic for the “age” field if (fieldName === 'age') { if (typeof value !== 'number') { throw TypeError('only numbers are accepted'); } if (value <= 0) throw TypeError('that is impossible'); } object[fieldName] = value; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); proxiedStudent.age = 'a'; // errors proxiedStudent.age = -1; // errors proxiedStudent.age = 12; // does not error
  • 35. Example: Value validation using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { set: function(object, fieldName, value) { // validation logic for the “age” field if (fieldName === 'age') { if (typeof value !== 'number') { throw TypeError('only numbers are accepted'); } if (value <= 0) throw TypeError('that is impossible'); } object[fieldName] = value; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); proxiedStudent.age = 'a'; // errors proxiedStudent.age = -1; // errors proxiedStudent.age = 12; // does not error
  • 36. Example: Value validation using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { set: function(object, fieldName, value) { // validation logic for the “age” field if (fieldName === 'age') { if (typeof value !== 'number') { throw TypeError('only numbers are accepted'); } if (value <= 0) throw TypeError('that is impossible'); } object[fieldName] = value; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); proxiedStudent.age = 'a'; // errors proxiedStudent.age = -1; // errors proxiedStudent.age = 12; // does not error
  • 37. Example: Value validation using Proxy const student = { firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { set: function(object, fieldName, value) { // validation logic for the “age” field if (fieldName === 'age') { if (typeof value !== 'number') { throw TypeError('only numbers are accepted'); } if (value <= 0) throw TypeError('that is impossible'); } object[fieldName] = value; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); proxiedStudent.age = 'a'; // errors proxiedStudent.age = -1; // errors proxiedStudent.age = 12; // does not error
  • 38. Example: Protect “id” field from deletion using a Proxy const student = { id: 'jackson-rowe', firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { deleteProperty: function(object, fieldName) { if (fieldName === 'id') return false; delete object[fieldName]; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); delete proxiedStudent.id // -> false console.log(proxiedStudent.id); // jackson-rowe
  • 39. Example: Protect “id” field from deletion using a Proxy const student = { id: 'jackson-rowe', firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { deleteProperty: function(object, fieldName) { if (fieldName === 'id') return false; delete object[fieldName]; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); delete proxiedStudent.id // -> false console.log(proxiedStudent.id); // jackson-rowe
  • 40. Example: Protect “id” field from deletion using a Proxy const student = { id: 'jackson-rowe', firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { deleteProperty: function(object, fieldName) { if (fieldName === 'id') return false; delete object[fieldName]; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); delete proxiedStudent.id // -> false console.log(proxiedStudent.id); // jackson-rowe
  • 41. Example: Protect “id” field from deletion using a Proxy const student = { id: 'jackson-rowe', firstName: 'Jackson', lastName: 'Rowe', }; const studentProxy = { deleteProperty: function(object, fieldName) { if (fieldName === 'id') return false; delete object[fieldName]; return true; } }; const proxiedStudent = new Proxy(student, studentProxy); delete proxiedStudent.id // -> false console.log(proxiedStudent.id); // jackson-rowe
  • 43. Reflect is all about “Reflection through introspection” - provides API to discover very low level information about code. source: keithcirkel.co.uk
  • 44. What can be done using Reflect ➔ Call a function using Reflect.apply() ➔ Define a property using Reflect.defineProperty() ➔ Delete a property using Control over Reflect.deleteProperty() ➔ Get a property value using Reflect.get() ➔ Set property value using Reflect.set() ➔ Check if a property exist using Reflect.has() Check MDN for a list of Reflect features
  • 45. What Reflect object offers are either a newer versions of existing methods or entirely new methods - allowing new levels of Reflection within JavaScript. source: keithcirkel.co.uk
  • 46. Example: Deleting a property using Reflect.deleteProperty() const student = { firstName: 'Jackson', lastName: 'Rowe', }; console.log(student.firstName); // -> Jackson Reflect.deleteProperty(student, 'firstName'); console.log(student.firstName); // -> undefined
  • 47. Example: Deleting a property using Reflect.deleteProperty() const student = { firstName: 'Jackson', lastName: 'Rowe', }; console.log(student.firstName); // -> Jackson Reflect.deleteProperty(student, 'firstName'); console.log(student.firstName); // -> undefined
  • 48. Example: Deleting a property using Reflect.deleteProperty() const student = { firstName: 'Jackson', lastName: 'Rowe', }; console.log(student.firstName); // -> Jackson Reflect.deleteProperty(student, 'firstName'); console.log(student.firstName); // -> undefined
  • 49. Example: Deleting a property using Reflect.deleteProperty() const student = { firstName: 'Jackson', lastName: 'Rowe', }; console.log(student.firstName); // -> Jackson Reflect.deleteProperty(student, 'firstName'); console.log(student.firstName); // -> undefined
  • 50. 100%Modern Browsers (Edge, Firefox, Safari, Chrome) 0%IE 11 100%Node 8 source: http://kangax.github.io/compat-table/es6/ Native support
  • 51. Resources ● Wikipedia - Metaprogramming ● Wikipedia - Reflection in Computer Science ● Mozilla - Metaprogramming ● Metaprogramming in ES6 by Keith Cirkel
  • 52. Credits Special thanks to all the people who made and released these awesome resources for free: ▷ MDN web docs ▷ Wikipedia and the contributors ▷ Keith Cirkel for the Metaprogramming series ▷ Presentation template by SlidesCarnival
  • 53. Thanks! Any questions? You can find me at: ➔ @mehdivk ➔ linkedin.com/in/valikhani/ ➔ [email protected]