ability to treat programs as their data. It means that a program could be designed to read, generate, analyse or transform other programs, and even modify itself while running. Wikipedia ” 3
expressions that contain programming commands, often composed from strings. • eval() 3. Expose the internals of the run-time engine to the programming code through application programming interfaces 4
delete • Function# name and Function# length • Function# bind , Function# call , and Function# apply • All of the available methods on Object are Reflection 7
using existing reflection tools before ES2015 • Object.getOwnPropertySymbols() 2. Symbols are not private • Object.getOwnSymbols() , Reflect.ownKeys(obj) 3. Enumerable Symbols can be copied to other objects • Object.assign(newObject, objectWithSymbols) 15
usually have string keys, but for non-public properties in inheritance hierarchies, accidental name clashes can become a problem. Against unauthorized access, use WeakMap() for private data in classes. Symbols having unique identities makes them ideal as keys of meta-level properties 17
static methods such as Promise.all(iterable), to return Promise from it’s prototype methods class TimeoutPromise extends Promise { static get [Symbol.species]() { return Promise; } } 23
versions of common existing Object/Function methods // Object.keys, Object.getOwnPropertyNames, Function.prototype.apply, etc • Different return values: Boolean instead of modified object • Operators as functions ESlint has a prefer-reflect rule 27
boolean The delete operator also “works” for non-object references(i.e. variables). And throws TypeError in strict mode if you try to delete a non-configurable own property. 30
get reaches a getter later in the prototype chain. Then it provides the value for this . var myObject = { foo: 1, bar: 2, get baz() { return this.foo + this.bar; },} assert( (myObject, 'baz') === 3); var myReceiverObject = { foo: 4, bar: 4,}; assert( (myObject, 'baz', myReceiverObject) === 8); 32
throw on non-objects, and receiver argument which acts as the this value if target[propKey] is a setter function. var myObject = { foo: 1, set bar(v) { return this.foo = v;}} var myReceiverObject = {foo: 0}; assert( (myObject, 'bar', 1, myReceiverObject)); assert(myReceiverObject.foo === 1); 34
customize operations performed on objects, wraps the target with handler hooks const proxy = ; If the handler doesn’t intercept an operation then it is performed on the target. That is, it acts as a fallback for the handler. In a way, the proxy wraps the target, so have an impact on performance . 44
'b', 'c'); console.log(arr[-1]); // c In the same way, you can use Proxy to exapnd the capability and make composition of other primitives like Map or Set 49
to make chainable API ⋯ function urlBuilder(domain) { var parts = []; var proxy = new Proxy(function () { var returnValue = domain + '/' + parts.join('/'); parts = []; return returnValue; }, { , get: (object, prop) => { parts.push(prop); ;}, }); } 50
service var api = urlBuilder('http://api.example.com'); assert(api.products.toys.dolls() === 'http://api.example.com/products/toys/dolls') Use this same pattern to make a tree traversal fluent API like: myDomIsh.div.span.i().textContent 51
= () => console.log('you called bar.'); foo = new Foo(); foo.bar(); //=> you called bar. foo.this_method_does_not_exist(); // Not existed this_method_does_not_exist property!' 53
bc = new Proxy({}, { get: (object, methodName) => { var parts = methodName.match(/base(\d+)toBase(\d+)/); var from = parts && parts[1]; var to = parts && parts[2]; if (!parts || from > 36 || to > 36 || from < 2 || to < 2) throw new Error(methodName + ' is not a function'); return (string) => parseInt(string, from).toString(to); }}); 54
'11011110101011011011111011101111'; bc.base2toBase16('11011110101011011011111011101111') === 'deadbeef'; This pattern could be also used for dynamic finder: Users.find_by_first_name_and_last_name('Keith', 'David'); 55
, preventExtensions , deleteProperty and defineProperty • Object.observe could mutate an object, where as Proxy has to return a new one • the unobserve function of Proxy is not a global • proxy-object-observe on npm 56
Reflect is all about Reflection through introspection 3. Proxy is all about Reflection through intercession 4. Not yet as advanced, No Operator Overloading 5. Useful for Tooling or Testing 57