Reflect Introduction:
The Reflect object has not been implemented in my node (v4.4.3), and babel (6.7.7) is not implemented. The new version of chrome is supported. ff has supported Proxy and Reflect for a long time. If you want node to support Reflect, you can install harmony-reflect;
Reflect is not a constructor. When used, it is called directly through Reflect.method(). Some methods of Reflect are similar to Proxy, and most Reflect methods native Objects have been re-implemented.
What to use Reflect
Here are a few reasons why Reflect is used. Translation address: Reflect, roughly translated:
1: More useful return value: Reflect has some methods like the Object method in ES5, such as: Reflect.getOwnPropertyDescriptor and Reflect.defineProperty. However, if the Object.defineProperty(obj, name, desc) is executed successfully, it will return obj, and other errors caused by other reasons. Reflect.defineProperty will only return false or true to indicate whether the object's properties have been set. The following code can be refactored:
try {Object.defineProperty(obj, name, desc);// property defined successfully} catch (e) {// possible failure (and might accidentally catch the wrong exception)}Reconstructed like this:
if (Reflect.defineProperty(obj, name, desc)) {// success} else {// failure}The other methods, such as Relect.set, Reflect.deleteProperty, Reflect.preventExtensions, Reflect.setPrototypeOf, can all be refactored;
2: Function operation. If you want to determine that an obj has a defined or inherits the attribute name, you can judge it in ES5 like this: name in obj;
Or delete an attribute: delete obj[name]. Although these are very useful, very short and clear, they must also be encapsulated into a class when they are to be used;
With Reflect, it helps you encapsulate, Reflect.has(obj, name), Reflect.deleteProperty(obj, name);
3: More reliable functional execution method: In ES, if you want to execute a function f and pass a set of parameters args to it, and bind this, you need to write this:
f.apply(obj, args)
However, the f application may be redefined as the user's own application, so it is more reliable to write this way:
Function.prototype.apply.call(f, obj, args)
The above code is too long and difficult to understand. With Reflect, we can be shorter and more concise and clearer:
Reflect.apply(f, obj, args)
4: Constructors in variadic parameter form: Imagine that you want to instantiate a constructor through parameters of uncertain length. In ES5, we can use extension symbols, which can be written like this:
var obj = new F(...args)
However, in ES5, extension characters are not supported, so we can only pass different parameters in F.apply or F.call. Unfortunately, F is a constructor, which is a scam, but with Reflect,
We can write this in ES5:
var obj = Reflect.construct(F, args)
5: This controls the accessor or reader: In ES5, if you want to read the attributes of an element or set the attributes as follows:
var name = ... // get property name as a stringobj[name] // generic property lookupobj[name] = value // generic property
The updateReflect.get and Reflect.set methods allow us to do the same thing, and it adds an extra parameter to the recciver, allowing us to set the object's setter and getter up and down this:
var name = ... // get property name as a stringReflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`Reflect.set(obj, name, value, wrapper) The accessor does not want to use its own method, but wants to redirect this to wrapper: var obj = {set foo(value) { return this.bar(); },bar: function() {alert(1);}};var wrapper = {bar : function() {console.log("wrapper");}}Reflect.set(obj, "foo", "value", wrapper);6: Avoid direct access to __proto__:
ES5 provides Object.getPrototypeOf(obj) to access the object's prototype, and ES6 provides also
Reflect.getPrototypeOf(obj) and Reflect.setPrototypeOf(obj, newProto), this is a new method to access and set the prototype of the object:
Reflect.apply usage
Reflect.apply is actually the Function.prototype.apply() substitute in ES5. Three parameters are required to execute Reflect.apply.
The first parameter is: the function to be executed;
The second parameter is: The context this that needs to be executed;
The third parameter is: is an array or pseudo-array, which will be used as a parameter to execute the function;
<script>let fn = function() {this.attr = [0,1,2,3];};let obj = {};Reflect.apply(fn, obj, [])console.log(obj); DEMO of <script>Reflect.apply: <script>Reflect.apply(Math.floor, undefined, [1.75]); // Output: 1;Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]); // Output: "hello"Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index; //Output: 4Reflect.apply("".charAt, "ponies", [3]); //Output: "i"</script>Reflect can be used in combination with Proxy: {var Fn = function(){};Fn.prototype.run = function() {console.log( "runs out" );};var ProxyFn = new Proxy(Fn, {construct (target,arugments) {console.log("proxy constructor");var obj = new target(...arugments);//How to use Reflect.apply;Reflect.apply(target.prototype.run, obj, arugments);return obj;}});new ProxyFn (); //The output first: "proxy constructor"; and then output: runs out}Reflect.construct(): Reflect.construct is actually an instantiation constructor. It is implemented through the argument form. The execution method is different. The effect is actually the same. The first parameter of construct is the constructor, and the second parameter is an array or a pseudo-array composed of parameters. The basic usage method is: var Fn = function(arg) {this.args = [arg]};console.log( new Fn(1), Reflect.construct(Fn,[1]) ); // The output is the same var d = Reflect.construct(Date, [1776, 6, 4]);d instanceof Date; // trued.getFullYear(); // 1776//So Reflect.construct and new construct so Reflect.construct and new construct are the same, at least so far...We can pass the third parameter to Reflect.construct, and the third parameter is a superclass. The new element will inherit this superclass; <script>function someConstructor() {}var result = Reflect.construct(Array, [], someConstructor);Reflect.getPrototypeOf(result); // someConstructor.prototypeArray.isArray(result); // true//orvar Fn = function() {this.attr = [1];};var Person = function() {};Person.prototype.run = function() {};console.log( Reflect.construct(Fn, [], Person) );</script> So we can use this to implement a special array, inherit the array, but we also have our own methods; var Fn = function() {Array.apply(this, arguments); this.shot = ()=> {console.log("heheda");};}; var arr = Reflect.construct(Fn, [])Reflect.defineProperty; Reflect.defineProperty returns a boolean value, and the attribute value is added to the object by direct assignment. Returns an entire object, if the addition fails, an error will be thrown; var obj = {};obj.x = 10;console.log(obj.x) //Output: 10; Add value using Reflect.defineProperty; <script>var obj = {};if( Reflect.defineProperty(obj, "x", {value : 7 }) ) {console.log("added success");}else{console.log("added success");};</script> If we execute preventExtensions, we report an error by defining the new property through Object.defindProperty, but there is no error by Reflect.defineProperty, and a false value is returned: var obj = {};Object.preventExtensions(obj);Object.defineProperty(obj, "x" , {value: 101,writable: false,enumerable: false,configurable: false});// Directly thrown wrong; console.log( Reflect.defineProperty(obj, "x", {value:101}) ) // Return false: If the value is directly assigned, the set value will be returned regardless of whether the value is assigned correctly, unless we manually confirm whether the property value of the object is set successfully; <script>var obj = {};Object.preventExtensions(obj);console.log( obj.aa = 1 ); //Output: 1; console.log(obj.aa) //Output: undefined;</script>Reflect.deleteProperty usage: Reflect.deleteProperty and Reflect.defineProperty use are similar. The operation results of Reflect.deleteProperty and delete obj.xx are the same. The difference is that the usage forms are different: one is an operator and the other is a function call; Reflect.deleteProperty(Object.freeze({foo: 1}), "foo"); // falsedelete Object.freeze({foo: 1}).foo; //Output: false; There are two necessary parameters for using the Reflect.get() method: the first is the obj target object, the second is the attribute name object, and the third is optional, which is the context of the reader (this); var obj = {};obj.foo = 1;console.log( obj.foo ); //Output: 1;console.log( Reflect.get(obj, "foo") ) //Output: 1;If Reflect.get has a third parameter, the third parameter will be used as the context of the reader: var Reflect = require('harmony-reflect'); var obj = {"foo" : 1,get bar() {return this.foo;}};var foo = {};foo.foo = "heheda";console.log(Reflect.get(obj, "bar", foo));Reflect.getOwnPropertyDescriptor() method: Get the property description through Reflect.getOwnPropertyDescriptor: Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");//You can also get it like this: Object.getOwnPropertyDescriptor({x:"1"},"x");//The difference between these two is that one can wrap the object, One does not: Reflect.getOwnPropertyDescriptor("hello",0); //Throw an exception Object.getOwnPropertyDescriptor("hello",0); //Output: {value: "h", writable: false, enumerable: true, configurable: false}Reflect.getPrototypeOf() method usage: Reflect.getPrototypeOf and Object.getPrototypeOf are the same, they both return the prototype of an object Reflect.getPrototypeOf({}); // Output: Object.prototypeReflect.getPrototypeOf(Object.prototype); // Output: nullReflect.getPrototypeOf(Object.create(null)); // Output: nullReflect.has The method of using Reflect.has is a bit like the operator: in, for example: xx in obj;<script>Reflect.has({x:0}, "x") // Output: true; Reflect.has({y:0}, "y") // Output: true; var obj = {x:0}; console.log( "x" in obj); var proxy = new Proxy(obj, { has : function(target, args) { console.log("Execute has method"); return Reflect.has(target,...args); } }); console.log( "x" in proxy); //Output: true; console.log(Reflect.has(proxy, "x")) //Output: true; </script> The obj of this demo is equivalent to becoming a method, it is useless, it just uses its has method: obj = new Proxy({}, {has(t, k) { return k.startsWith("door"); }}); Reflect.has(obj, "doorbell"); // trueReflect.has(obj, "dormitory"); // falseReflect.isExtensible() use // Now this element can be extended; var empty = {};Reflect.isExtensible(empty); // === true// Use preventExtensions method to prevent this object from extending new attributes; Reflect.preventExtensions(empty); Reflect.isExtensible(empty); // === false// This object cannot extend new attributes, and the writable attributes can still be changed var sealed = Object.seal({});Reflect.isExtensible(sealed); // === false// This object is completely frozen var frozen = Object.freeze({});Reflect.isExtensible(frozen); // === false The difference between Reflect.isExtensible and Object.isExtensible is that if the parameter is not correct, one will throw the wrong one, and the other will just return true or false: Reflect.isExtensible(1);// Wrong throw: 1 is not an objectObject.isExtensible(1);// Return false; Reflect.ownKeys() method use: Reflect.ownKeys, Object does not have the ownKeys method, Reflect.ownKeysz Its function is to return the keys of the object; console.log(Reflect.ownKeys({"a":0,"b":1,"c":2,"d":3})); // Output: ["a", "b", "c", "d"]console.log(Reflect.ownKeys([])); // ["length"]var sym = Symbol.for("comet"); var sym2 = Symbol.for("meteor"); var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0, [sym2]: 0, "-1": 0, "8": 0, "second str": 0};Reflect.ownKeys(obj); //Output: / [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]Reflect.ownKeys is sorted by: first display the numbers, the numbers are sorted by size, and then the strings are sorted by the order of insertion. Finally, the keys of the symbol type are also sorted according to the order of insertion; the sorting occurs because when you assign a value to an object attribute, the sorting rule of the object key is to first number, in a string, and finally the data of the symbol type; the usage method of Reflect.preventExtensions(): Object also has a preventExtensions method, which is a little different from Reflect.preventExtensions(). If the Reflect.preventExtensions parameter is not an object, it will throw an error; var empty = {};Reflect.isExtensible(empty); // === true// The object after executing preventExtensions can be modified; Reflect.preventExtensions(empty); Reflect.isExtensible(empty); // === falseReflect.preventExtensions(1);// TypeError: 1 is not an objectObject.preventExtensions(1);// No error is thrown, it will return: 1Reflect.set()Reflect.set method is similar to get; var obj = {};Reflect.set(obj, "prop", "value"); // Output: trueconsole.log( obj.prop ); // Output: "value"var arr = ["duck", "duck", "duck"];Reflect.set(arr, 2, "goose"); // trueconsole.log( arr[2] ); // "goose"Reflect.set(arr, "length", 1); // trueconsole.log( arr );// ["duck"];Reflect.set(obj) is equivalent to Reflect.set(obj, undefined, undefined);var obj = {};Reflect.set(obj); // Output: true//The above code is equivalent to Reflect.set(obj, undefined, undefined);Reflect.getOwnPropertyDescriptor(obj, "undefined");// { value: undefined, writable: true, enumerable: true, configurable: true }Reflect.set can also have a fourth parameter, which will be used as this of stter;var obj = {value : 10,set key( value ) {console.log("setter");this.value = value;},get key() {return this.value;}};Reflect.set(obj,"key","heheda", obj);console.log(obj);Reflect.setPrototypeOf()Reflect.setPrototypeOf() method is similar to Object.setPrototypeOf. It will set a prototype for the object, which is to change the object's __proto__ attribute...;Reflect.setPrototypeOf({}, Object.prototype); // Output true// To the object array [[Prototype]] is null.Reflect.setPrototypeOf({}, null); // true// At this time, obj.__proto__ is undefined//Free the object and reset [[prototype]]Reflect.setPrototypeOf(Object.freeze({}), null); // false// If the prototype chain is dependent on the loop, it will return false.var target = {};var proto = Object.create(target);Reflect.setPrototypeOf(target, proto); // false