May 08, 2021 ES6
3. Reflect.get(target, name, receiver)
4. Reflect.set(target, name, value, receiver)
6. Reflect.deleteProperty(obj, name)
7. Reflect.construct(target, args)
8. Reflect.getPrototypeOf(obj)
9. Reflect.setPrototypeOf(obj, newProto)
10.. Reflect.apply(func, thisArg, args)
11.. Reflect.defineProperty(target, propertyKey, attributes)
12.. Reflect.getOwnPropertyDescriptor(target, propertyKey)
13.. Reflect.isExtensible (target)
Reflect
object,
Proxy
the Proxy object, is a new API that ES6
操作对象
manipulate objects.
Reflect objects are designed for several purposes.
(1) Place some methods of object objects that are clearly within the language, such as Object.defineProperty, on the Reflect object. A t this stage, some methods are deployed on both Object and Reflect objects, and new methods will be deployed only on Reflect objects in the future. That is, you can get the method inside the language from the Reflect object.
(2) Modify the return results of some Object methods to make them more reasonable. For example, Object.defineProperty (obj, name, desc) throws an error when a property cannot be defined, while Reflect.defineProperty (obj, name, desc) returns false.
// 老写法
try {
Object.defineProperty(target, property, attributes);
// success
} catch (e) {
// failure
}
// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// failure
}
(3) Make object operations functional. Some Object operations are commandive, such as name in obj and delete obj(name), while Reflect.has (obj, name) and Reflect.deleteProperty (obj, name) make them functional behaviors.
// 老写法
'assign' in Object // true
// 新写法
Reflect.has(Object, 'assign') // true
(4) The
Reflect
object
Proxy
of the Proxy object, and as long as it is the method of the Proxy object, you can find the method on the Reflect object. T
his makes it easy for the Proxy object to call the corresponding Reflect method to complete the default behavior as the basis for modifying the behavior.
That is, no matter how Proxy modifies the default behavior, you can always get the default behavior on Reflect.
Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target, name, value, receiver);
if (success) {
console.log('property ' + name + ' on ' + target + ' set to ' + value);
}
return success;
}
});
In the code above, the Proxy method intercepts the property assignment behavior of the target object. It uses the Reflect.set method to assign values to the properties of the object, ensuring that the original behavior is completed before additional functionality is deployed.
Here's another example.
var loggedObj = new Proxy(obj, {
get(target, name) {
console.log('get', target, name);
return Reflect.get(target, name);
},
deleteProperty(target, name) {
console.log('delete' + name);
return Reflect.deleteProperty(target, name);
},
has(target, name) {
console.log('has' + name);
return Reflect.has(target, name);
}
});
In the code above, each of the interception operations of the Proxy object (get, delete, has) calls the corresponding Reflect method internally to ensure that the native behavior performs normally. The work added is to output one line of logs for each operation.
With The Reflect object, many operations are easier to read.
// 老写法
Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1
// 新写法
Reflect.apply(Math.floor, undefined, [1.75]) // 1
Reflect
are
13
Reflect objects.
Most of the above methods work the same as the object object's method of the same name, and it corresponds to the proxy object's method one-to-one. Here's an explanation of them.
Reflect.get
finds and returns the name property of the target object, and if there is no such property, undefined is returned.
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
}
Reflect.get(myObject, 'foo') // 1
Reflect.get(myObject, 'bar') // 2
Reflect.get(myObject, 'baz') // 3
If
name
property
读取函数
read function (getter), the this-bound receiver of the read function.
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
};
var myReceiverObject = {
foo: 4,
bar: 4,
};
Reflect.get(myObject, 'baz', myReceiverObject) // 8
If the first argument is not an object, the Reflect.get method reports an error.
Reflect.get(1, 'foo') // 报错
Reflect.get(false, 'foo') // 报错
Reflect.set
the
target
of the target object to equal value.
var myObject = {
foo: 1,
set bar(value) {
return this.foo = value;
},
}
myObject.foo // 1
Reflect.set(myObject, 'foo', 2);
myObject.foo // 2
Reflect.set(myObject, 'bar', 3)
myObject.foo // 3
If the name property sets the assignment function, the assignment function's this binding receiver.
var myObject = {
foo: 4,
set bar(value) {
return this.foo = value;
},
};
var myReceiverObject = {
foo: 0,
};
Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1
Note that If the Proxy object is used in association with the Reflect object, which intercepts the assignment, which completes the default behavior of the assignment, and the receiver is passed in, Reflect.set triggers the Proxy.defineProperty intercept.
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
In the code above, The Proxy.set intercept uses Reflect.set and is passed in to receiver, triggering the Proxy.defineProperty intercept. T his is because the receiver parameter of Proxy.set always points to the current Proxy instance (i.e., the obj of the example above), and once Reflect.set is passed in to receiver, the property is assigned to the receiver (that is, obj), causing the defineProperty blocking to be triggered. If Reflect.set does not pass in receiver, the defineProperty intercept is not triggered.
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
If the first argument is not an object, Reflect.set will report an error.
Reflect.set(1, 'foo', {}) // 报错
Reflect.set(false, 'foo', {}) // 报错
Reflect.has
method corresponds to the in operator inside
in
name in obj
var myObject = {
foo: 1,
};
// 旧写法
'foo' in myObject // true
// 新写法
Reflect.has(myObject, 'foo') // true
If the first argument of the Reflect.has() method is not an object, an error is reported.
Reflect.deleteProperty
is equivalent
delete obj[name]
to remove the properties of an object.
const myObj = { foo: 'bar' };
// 旧写法
delete myObj.foo;
// 新写法
Reflect.deleteProperty(myObj, 'foo');
The method returns a Boolean value. If the deletion succeeds, or if the deleted property does not exist, true is returned;
If the first argument of the Reflect.deleteProperty() method is not an object, an error is reported.
Reflect.construct
is equivalent
new target(...args)
which provides a way to call constructors without using new.
function Greeting(name) {
this.name = name;
}
// new 的写法
const instance = new Greeting('张三');
// Reflect.construct 的写法
const instance = Reflect.construct(Greeting, ['张三']);
If the first argument of the Reflect.construct() method is not a function, an error is reported.
Reflect.getPrototypeOf
used to
__proto__
of an object, corresponding to Object.getPrototypeOf (obj).
const myObj = new FancyThing();
// 旧写法
Object.getPrototypeOf(myObj) === FancyThing.prototype;
// 新写法
Reflect.getPrototypeOf(myObj) === FancyThing.prototype;
One of the differences between Reflect.getPrototypeOf and Object.getPrototypeOf is that if the parameter is not an object, Object.getPrototypeOf converts the parameter into an object and then runs it, while Reflect.getPrototypeOf will report an error.
Object.getPrototypeOf(1) // Number {[[PrimitiveValue]]: 0}
Reflect.getPrototypeOf(1) // 报错
Reflect.setPrototypeOf
目标对象
method is used to
原型
the prototype of the target object, corresponding to the Object.setPrototypeOf (obj, newProto) method.
It returns a Boolean value to indicate whether the setting was successful.
const myObj = {};
// 旧写法
Object.setPrototypeOf(myObj, Array.prototype);
// 新写法
Reflect.setPrototypeOf(myObj, Array.prototype);
myObj.length // 0
If the prototype of the target object cannot be set (for example, the target object does not extend), the Reflect.setPrototypeOf method returns false.
Reflect.setPrototypeOf({}, null)
// true
Reflect.setPrototypeOf(Object.freeze({}), null)
// false
If the first argument is not an object, Object.setPrototypeOf returns the first argument itself, and Reflect.setPrototypeOf will report an error.
Object.setPrototypeOf(1, {})
// 1
Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object
If the first argument is undefined or null, Object.setPrototypeOf and Reflect.setPrototypeOf will report errors.
Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefined
Reflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object
Reflect.apply
method is
Function.prototype.apply.call(func, thisArg, args)
which is used to bind this object and execute a given function.
In general, if you want to bind this object of a function, you can write fn.apply (obj, args) like this, but if the function defines its own apply method, it can only be written as Function.prototype.apply.call (fn, obj, args), which can be simplified with a Reflect object.
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, []);
Reflect.defineProperty
is basically
Object.defineProperty
and is used to define properties for objects.
In the future, the latter will be phased out, so use Reflect.defineProperty instead of it from now on.
function MyDate() {
/*…*/
}
// 旧写法
Object.defineProperty(MyDate, 'now', {
value: () => Date.now()
});
// 新写法
Reflect.defineProperty(MyDate, 'now', {
value: () => Date.now()
});
If the first argument of Reflect.defineProperty is not an object, an error is thrown, such as Reflect.defineProperty (1, 'foo').
This method can be used in conjunction with Proxy.defineProperty.
const p = new Proxy({}, {
defineProperty(target, prop, descriptor) {
console.log(descriptor);
return Reflect.defineProperty(target, prop, descriptor);
}
});
p.foo = 'bar';
// {value: "bar", writable: true, enumerable: true, configurable: true}
p.foo // "bar"
In the code above, Proxy.defineProperty sets an intercept on property assignments, and then uses Reflect.defineProperty to complete the assignment.
Reflect.getOwnPropertyDescriptor
basically
Object.getOwnPropertyDescriptor
is used to get a description object for a specified property and will replace the latter in the future.
var myObject = {};
Object.defineProperty(myObject, 'hidden', {
value: true,
enumerable: false,
});
// 旧写法
var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden');
// 新写法
var theDescriptor = Reflect.getOwnPropertyDescriptor(myObject, 'hidden');
One of the differences between Reflect.getOwnPropertyDescriptor and Object.getOwnPropertyDescriptor is that if the first argument is not an object, Object.getOwnPropertyDescriptor (1, 'foo') does not report an error and returns undefined instead Reflect.getOwnPropertyDescriptor (1, 'foo') throws an error indicating that the argument is illegal.
Reflect.isExtensible
corresponds
Object.isExtensible
a
布尔值
that indicates whether the current object is
是否可扩展
const myObject = {};
// 旧写法
Object.isExtensible(myObject) // true
// 新写法
Reflect.isExtensible(myObject) // true
If the argument is not an object, Object.isExtensible returns false because the non-object is inherently unextendable, and Reflect.isExtensible reports an error.
Object.isExtensible(1) // false
Reflect.isExtensible(1) // 报错
Reflect.preventExtensions
Object.preventExtensions
which makes an object
不可扩展
It returns a Boolean value to indicate whether the operation was successful.
var myObject = {};
// 旧写法
Object.preventExtensions(myObject) // Object {}
// 新写法
Reflect.preventExtensions(myObject) // true
If the argument is not an object, Object.preventExtensions reports an error in the ES5 environment, an incoming argument is returned in the ES6 environment, and Reflect.preventExtensions reports an error.
// ES5 环境
Object.preventExtensions(1) // 报错
// ES6 环境
Object.preventExtensions(1) // 1
// 新写法
Reflect.preventExtensions(1) // 报错
Reflect.ownKeys
used to return all the properties of an object, basically the same as
Object.getOwnPropertyNames
and
Object.getOwnPropertySymbols
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)]
If the first argument of the Reflect.ownKeys() method is not an object, an error is reported.
Observer mode
观察者模式
to a function that
自动观察数据对象
and executes automatically when the object changes.
const person = observable({
name: '张三',
age: 20
});
function print() {
console.log( ${person.name}, ${person.age} )
}
observe(print);
person.name = '李四';
// 输出
// 李四, 20
In the above code, the data object person is the observation target, and the function print is the observer. Once the data object changes, the print is executed automatically.
Below, use Proxy to write the simplest implementation of an observer pattern, which is to implement both observable and observe functions. The idea is that the observable function returns a Proxy proxy for the original object, intercepts assignments, and triggers individual functions that act as observers.
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;
}
In the above code, a Set collection is
Set 集合
and all observer functions are placed in the set. T
he observable function then returns the agent of the original object, blocking the assignment operation.
In the intercept function set, all observers are automatically executed.