ES6 Reflect method summary (reproduced)

Original author address: https://www.cnblogs.com/houfee/p/11369609.html

1 Overview

  • Put some methods of the Object object that are obviously internal to the language (such as Object.defineProperty) on the Reflect object.

  • Modify the return results of some Object methods to make them more reasonable. For example, Object.defineProperty(obj, name, desc) will throw an error when the property cannot be defined, while Reflect.defineProperty(obj, name, desc) will return false.

  • Let Object operations become functional behaviors. Certain Object operations are imperative, such as name in obj and delete obj[name], while Reflect.has(obj, name) and Reflect.deleteProperty(obj, name) make them functional behaviors.

  • The methods of the Reflect object correspond to the methods of the Proxy object one-to-one. As long as it is a method of the Proxy object, the corresponding method can be found on the Reflect object.

// 老写法
Function.prototype.apply.call(Math.floor, undefined, [8.75]) // 8

// 新写法
Reflect.apply(Math.floor, undefined, [20.5]) // 20

2. Static method

The Reflect object has 13 static methods in total:

Copy code

Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)

Copy code

1.Reflect.get(target, name, receiver)

The Reflect.get method finds and returns the name property of the target object, if there is no such property, it returns undefined.

Copy code

var obj = {
    name: 'houfee',
    age: 24,
    get func() {
        return this.name + this.age
    }
}
console.log(Reflect.get(obj, 'name')) // houfee
console.log(Reflect.get(obj, 'age')) // 24
console.log(Reflect.get(obj, 'func')) // houfee24

Copy code

If a read function (getter) is deployed in the name attribute, the this of the read function is bound to the receiver.

Change this to

Copy code

var obj = {
    name: 'houfee',
    age: 24,
    get func() {
        return this.name + this.age
    }
}
var obj2 = {
    name: 'houyue',
    age: 14,
}
console.log(Reflect.get(obj, 'name')) // houfee
console.log(Reflect.get(obj, 'age')) // 24
console.log(Reflect.get(obj, 'func', obj2)) // houyue14

Copy code

If the first parameter is not an object, the Reflect.get method will report an error.

 

2.Reflect.set(target, name, value, receiver)

The Reflect.set method sets the name property of the target object equal to value.

Copy code

var obj = {
    name: 'houfee',
    set func(value) {
        return this.name = value
    }
}
var obj2 = {
    name: 'houyue'
}
console.log(Reflect.set(obj, 'name', 'houyue')) // true
console.log(Reflect.set(obj, 'func', 'houyue')) // true
console.log(obj) // {name: "houyue", age: 24}

Copy code

If an assignment function is set for the name attribute, the this of the assignment function is bound to the receiver.

Copy code

var obj = {
    name: 'houfee',
    set func(value) {
        return this.name = value
    }
}
var obj2 = {
    name: 'zhangsan'
}
console.log(Reflect.set(obj, 'func', 'houyue', obj2)) // true
console.log(obj) // {name: "houfee"}
console.log(obj2) // {name: "houyue"}

Copy code

Note that if the Proxy object and the Reflect object are used in combination, the former intercepts the assignment operation, the latter completes the default behavior of the assignment, and the receiver is passed in, then Reflect.set will trigger the Proxy.defineProperty interception.

Proxy  and  Reflect  work together:

Copy code

let p = {
    a: 'a'
};
let handler = {
    set(target, key, value, receiver) {
        console.log('set');
        Reflect.set(target, key, value, receiver)
    },
    defineProperty(target, key, attribute) {
        console.log('defineProperty');
        Reflect.defineProperty(target, key, attribute);
    }
};
let obj = new Proxy(p, handler);
obj.a = 'A';
// set
// defineProperty

Copy code

In the above code, Reflect.set is used in the Proxy.set interception, and the receiver is passed in, which triggers the Proxy.defineProperty interception. This is because the receiver parameter of Proxy.set always points to the current Proxy instance (that is, obj in the above example), and once Reflect.set is passed to the receiver, the property will be assigned to the receiver (that is, obj), which triggers defineProperty interception . If Reflect.set is not passed into the receiver, then defineProperty interception will not be triggered.

Copy code

let p = {
    a: 'a'
};
let handler = {
    set(target, key, value, receiver) {
        console.log('set');
        Reflect.set(target, key, value)
    },
    defineProperty(target, key, attribute) {
        console.log('defineProperty');
        Reflect.defineProperty(target, key, attribute);
    }
};
let obj = new Proxy(p, handler);
obj.a = 'A'; // set

Copy code

If the first parameter is not an object, Reflect.set will report an error.

 

3.Reflect.has(obj, name)

The Reflect.has method corresponds to the in operator in name in obj.

Copy code

var myObject = {
    foo: 1,
};
// 旧写法
console.log('foo' in myObject); // true
// 新写法
console.log(Reflect.has(myObject, 'foo')); // true

Copy code

This method returns a boolean value. If the deletion is successful, or the deleted attribute does not exist, return true; if the deletion fails, the deleted attribute still exists, and false is returned.

 

4. Reflect.deleteProperty(obj, name)

The Reflect.deleteProperty method is equivalent to delete obj[name] and is used to delete the properties of an object.

Copy code

const myObj = {
    foo: 'bar'
};
// 旧写法
delete myObj.foo;
// 新写法
Reflect.deleteProperty(myObj, 'foo');

Copy code

This method returns a boolean value. If the deletion is successful, or the deleted attribute does not exist, return true; if the deletion fails, the deleted attribute still exists, and false is returned.

 

5. Reflect.construct(target, args)

The Reflect.construct method is equivalent to new target(...args), which provides a way to call the constructor without using new.

Copy code

function Func(name) {
    this.name = name
}
// new 的写法
const instance = new Func('张三')
// Reflect.construct 的写法
const instance = Reflect.construct(Func, ['张三'])

Copy code

 

6. Reflect.getPrototypeOf(obj)

The Reflect.getPrototypeOf method is used to read the proto  property of an object  , corresponding to Object.getPrototypeOf(obj).

Copy code

function Func(name) {
    this.name = name
}
// new 的写法
const instance = new Func('张三')
Object.getPrototypeOf(instance) === Func.prototype
// Reflect.construct 的写法
const instance = Reflect.construct(Func, ['张三'])
Reflect.getPrototypeOf(instance) === Func.prototype

Copy code

One difference between Reflect.getPrototypeOf and Object.getPrototypeOf is:

If the parameter is not an object, Object.getPrototypeOf will convert the parameter to an object and then run, and Reflect.getPrototypeOf will report an error.

 

7. Reflect.setPrototypeOf(obj, newProto)

The Reflect.setPrototypeOf method is used to set the proto  property of the object  and returns the first parameter object, corresponding to Object.setPrototypeOf(obj, newProto).

Copy code

function Func(name) {
    this.name = name
}
function Age(age) {
    this.age = age
}
// new 的写法 将 Age 挂载到 instance 实例的原型上
var instance = new Func('张三')
Object.setPrototypeOf(instance, Age.prototype)
// Reflect.construct 的写法
var instance = Reflect.construct(Func, ['张三'])
Reflect.setPrototypeOf(instance, Age.prototype)

Copy code

If the first parameter is not an object, Object.setPrototypeOf will return the first parameter itself, and Reflect.setPrototypeOf will report an error.

If the first parameter is undefined or null, Object.setPrototypeOf and Reflect.setPrototypeOf will both report an error.

 

8. Reflect.apply(func, thisArg, args)

The Reflect.apply method is equivalent to Function.prototype.apply.call(func, thisArg, args), which is used to execute the given function after binding this object. Generally speaking, if you want to bind the this object of a function, you can write fn.apply(obj, args), but if the function defines its own apply method, it can only be written as Function.prototype.apply.call(fn, obj, args), using Reflect objects can simplify this operation.

Copy code

const ages = [11, 33, 12, 54, 18, 96];
// 旧写法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);
const type = Object.prototype.toString.call(youngest);
// 新写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);
const type = Reflect.apply(Object.prototype.toString, youngest, []);

Copy code

 

9. Reflect.defineProperty(target, propertyKey, attributes)

The Reflect.defineProperty method is basically equivalent to Object.defineProperty and is used to define properties for objects. In the future, the latter will be gradually abolished, please use Reflect.defineProperty to replace it from now on.

Copy code

function MyDate() {
    /*…*/
}
// 旧写法
Object.defineProperty(MyDate, 'now', {
    value: () => Date.now()
});
// 新写法
Reflect.defineProperty(MyDate, 'now', {
    value: () => Date.now()
});

Copy code

If the first parameter of Reflect.defineProperty is not an object, an error will be thrown, such as Reflect.defineProperty(1,'foo').

 

10. Reflect.getOwnPropertyDescriptor(target, propertyKey)

Reflect.getOwnPropertyDescriptor is basically equivalent to Object.getOwnPropertyDescriptor, which is used to get the description object of the specified property, which will be replaced in the future.

Copy code

var myObject = {};
Object.defineProperty(myObject, 'hidden', {
    value: true,
    enumerable: false,
});
// 旧写法
var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden');
// 新写法
var theDescriptor = Reflect.getOwnPropertyDescriptor(myObject, 'hidden');

Copy code

One difference between Reflect.getOwnPropertyDescriptor and Object.getOwnPropertyDescriptor is that if the first parameter is not an object, Object.getOwnPropertyDescriptor(1,'foo') does not report an error and returns undefined,

And Reflect.getOwnPropertyDescriptor(1,'foo') will throw an error, indicating that the parameter is illegal.

 

11.Reflect.isExtensible (target)

The Reflect.isExtensible method corresponds to Object.isExtensible and returns a Boolean value indicating whether the current object is extensible.

const myObject = {};
// 旧写法
Object.isExtensible(myObject) // true
// 新写法
Reflect.isExtensible(myObject) // true

If the parameter is not an object, Object.isExtensible will return false because non-objects are inherently non-extensible, and Reflect.isExtensible will report an error.

 

12. Reflect.preventExtensions(target)

Reflect.preventExtensions corresponds to the Object.preventExtensions method, used to make an object non-extensible. It returns a Boolean value indicating whether the operation was successful.

var myObject = {};
// 旧写法
Object.preventExtensions(myObject) // Object {}
// 新写法
Reflect.preventExtensions(myObject) // true

If the parameter is not an object, Object.preventExtensions will report an error in the ES5 environment, and the passed parameter will be returned in the ES6 environment, and Reflect.preventExtensions will report an error.

 

13. Reflect.ownKeys (target)

The Reflect.ownKeys method is used to return all the properties of the object, basically equivalent to the sum of Object.getOwnPropertyNames and Object.getOwnPropertySymbols.

Copy code

var myObject = {
    foo: 1,
    bar: 2,
    [Symbol.for('baz')]: 3,
    [Symbol.for('bing')]: 4,
};
// 旧写法
Object.getOwnPropertyNames(myObject)
// ['foo', 'bar']
Object.getOwnPropertySymbols(myObject)
//[Symbol(baz), Symbol(bing)]
Reflect.ownKeys(myObject)
// ['foo', 'bar', Symbol(baz), Symbol(bing)]

Copy code

 

3. Example: Use Proxy to implement observer mode

Observer mode refers to the function that automatically observes the data object. Once the object changes, the function will automatically execute.

 

Copy code

const person = observable({
    name: '张三',
    age: 20
});

function print() {
    console.log(`${person.name}, ${person.age}`)
}
observe(print);
person.name = '李四'; // 输出 // 李四, 20

Copy code

In the above code, the data object person is the observation target, and the function print is the observer. Once the data object changes, print will be executed automatically.

Next, use Proxy to write the simplest implementation of the observer pattern, which implements the two functions observable and observe. The idea is that the observable function returns a proxy proxy of the original object, intercepts assignment operations, and triggers various functions that act as observers.

Copy code

const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {
    set
});

function set(target, key, value, receiver) {
    const result = Reflect.set(target, key, value, receiver);
    queuedObservers.forEach(observer => observer());
    return result;
}

Copy code

In the above code, a Set set is defined first, and all observer functions are put into this set. Then, the observable function returns the proxy of the original object, intercepting the assignment operation. In the intercept function set, all observers are automatically executed.

Guess you like

Origin blog.csdn.net/qq_40289624/article/details/108869670