/**
* Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。
* 这些方法与proxy handlers (en-US)的方法相同。
* Reflect不是一个函数对象,因此它是不可构造的。
* 与大多数全局对象不同Reflect并非一个构造函数,所以不能通过new运算符对其进行调用,
* 或者将Reflect对象作为一个函数来调用。Reflect的所有属性和方法都是静态的(就像Math对象)。
* Reflect 对象提供了以下静态方法,这些方法与proxy handler methods (en-US)的命名相同.
* 其中的一些方法与 Object相同, 尽管二者之间存在 某些细微上的差别 .
*/
// console.log(Object.prototype.isPrototypeOf(Reflect));
/**
* Reflect.apply()
* 静态方法 Reflect.apply() 通过指定的参数列表发起对目标(target)函数的调用。
* target
* 目标函数。
* thisArgument
* target函数调用时绑定的this对象。
* argumentsList
* target函数调用时传入的实参列表,该参数应该是一个类数组的对象。
* 返回值是调用完带着指定参数和 this 值的给定的函数后返回的结果。
* 如果 target 对象不可调用,抛出 TypeError。
*/
// Reflect.apply(target, thisArgument, argumentsList)
// console.log(Reflect.apply(String.prototype.charAt, 'apple', [2]));//p
/**
* Reflect.construct()
* Reflect.construct() 方法的行为有点像 new 操作符 构造函数 ,
* 相当于运行 new target(...args).
* target
* 被运行的目标构造函数
* argumentsList
* 类数组,目标构造函数调用时的参数。
* newTarget 可选
* 作为新创建对象的原型对象的constructor属性, 参考 new.target 操作符,默认值为target。
* 以target(如果newTarget存在,则为newTarget)函数为构造函数,
* argumentList为其初始化参数的对象实例。
* 如果target或者newTarget不是构造函数,抛出TypeError,异常。
*/
//Reflect.construct(target, argumentsList[, newTarget])
function oneClass() {
this.name = 'one';
// console.log(new.target);
};
function twoClass(...args) {
// console.log('enter', args)
this.name = 'two' + args[3];
// console.log(new.target);
};
const obj1 = Reflect.construct(twoClass, [1, 2, 3, 4, 5], oneClass);//enter,[1,2,3,4,5]
// console.log(obj1, obj1 instanceof oneClass);// {name:'two4'},true
const obj2 = Reflect.construct(twoClass, [1, 2, 3, 4, 5]);//enter,[1,2,3,4,5]
// console.log(obj2, obj2 instanceof twoClass); //{ name: 'two4' }, true
//当使用Object.create()和Function.prototype.apply()时,
//如果不使用new操作符调用构造函数,构造函数内部的new.target值会指向undefined。
//当调用Reflect.construct()来创建对象,
//new.target值会自动指定到target(或者newTarget,前提是newTarget指定了)。
/**
* Reflect.defineProperty()
* 静态方法 Reflect.defineProperty() 基本等同于 Object.defineProperty() 方法,
* 唯一不同是返回 Boolean 值。
* target
* 目标对象。
* propertyKey
* 要定义或修改的属性的名称。
* attributes
* 要定义或修改的属性的描述。
* Boolean 值指示了属性是否被成功定义。
* 如果target不是 Object,抛出一个 TypeError。
* => boolean
*/
//Reflect.defineProperty(target, propertyKey, attributes)
const obj3 = {};
const target3 = Reflect.defineProperty(obj3, 'name', {
value: 'obj3',
writable: true,
enumerable: true,
configurable: true
});
// console.log(target3, obj3);//true, {name: 'obj3' }
// Object.defineProperty 方法,如果成功则返回一个对象,否则抛出一个 TypeError 。
// 另外,当定义一个属性时,你也可以使用 try...catch 去捕获其中任何的错误。
// 而因为 Reflect.defineProperty 返回 Boolean 值作为成功的标识,所以只能使用 if...else
/**
* Reflect.deleteProperty()
* 静态方法 Reflect.deleteProperty() 允许用于删除属性。它很像 delete operator ,但它是一个函数。
* Boolean 值表明该属性是否被成功删除。
* => boolean
*/
//Reflect.deleteProperty(target, propertyKey)
const obj4 = {
name: 'obj4',
age: '4'
};
const target4 = Reflect.deleteProperty(obj4, 'age');
// console.log(obj4, target4);//{name:"obj4"},true
/**
* Reflect.get()
* Reflect.get()方法与从 对象 (target[propertyKey]) 中读取属性类似,
* 但它是通过一个函数执行来操作的。
* target
* 需要取值的目标对象
* propertyKey
* 需要获取的值的键值
* receiver
* 如果target对象中指定了getter,receiver则为getter调用时的this值。
* Reflect.get方法允许你从一个对象中取属性值。就如同属性访问器 语法,但却是通过函数调用来实现。
* => propertyValue
*/
//Reflect.get(target, propertyKey[, receiver])
const obj5 = {
name: 'obj5',
age: 5
};
const proxy5 = new Proxy(obj5, {
get(t, p, r) {
return t[p];
}
});
const target5 = Reflect.get(proxy5, 'name');
// console.log(target5, proxy5, obj5);
/**
* Reflect.getOwnPropertyDescriptor()
* 静态方法 Reflect.getOwnPropertyDescriptor() 与 Object.getOwnPropertyDescriptor() 方法相似。
* 如果在对象中存在,则返回给定的属性的属性描述符。否则返回 undefined。
* target
* 需要寻找属性的目标对象。
* propertyKey
* 获取自己的属性描述符的属性的名称。
* 如果属性存在于给定的目标对象中,则返回属性描述符;否则,返回 undefined.
* => propertyDescriptor / undefined
*/
//Reflect.getOwnPropertyDescriptor(target, propertyKey)
const obj6 = {
name: 'obj6',
age: '6',
};
const target6 = Reflect.getOwnPropertyDescriptor(obj6, 'name');
const targetO6 = Object.getOwnPropertyDescriptor('123', 0);
// console.log(target6, targetO6);
//Reflect.getOwnPropertyDescriptor方法返回一个属性描述符,如果给定的属性存在于对象中,否则返回 undefined 。
//与 Object.getOwnPropertyDescriptor() 的唯一不同在于如何处理非对象目标。
// 如果该方法的第一个参数不是一个对象(一个原始值),那么将造成 TypeError 错误。
// 而对于 Object.getOwnPropertyDescriptor,非对象的第一个参数将被强制转换为一个对象处理。
/**
* Reflect.getPrototypeOf()
* 静态方法 Reflect.getPrototypeOf() 与 Object.getPrototypeOf() 方法几乎是一样的。
* 都是返回指定对象的原型(即内部的 [[Prototype]] 属性的值)。
* 给定对象的原型。如果给定对象没有继承的属性,则返回 null。
* => target.prototype / null
*/
//Reflect.getPrototypeOf(target)
const obj7 = {
name: 'obj7',
age: 7
};
const target7 = Reflect.getPrototypeOf(obj7);
// console.log(target7 === Object.prototype, Object.prototype.isPrototypeOf(obj7));
/**
* Reflect.has()
* 静态方法 Reflect.has() 作用与 in 操作符 相同。
* 一个 Boolean 类型的对象指示是否存在此属性。
* => boolean
*/
//Reflect.has(target, propertyKey)
const obj8 = {
name: 'obj8',
age: 8
};
const obj8Prototype = {
level: 1
};
Object.setPrototypeOf(obj8, obj8Prototype);
// console.log(obj8Prototype.isPrototypeOf(obj8), Reflect.has(obj8, 'level'));
/**
* Reflect.isExtensible()
* 静态方法 Reflect.isExtensible() 判断一个对象是否可扩展 (即是否能够添加新的属性)。
* 与它 Object.isExtensible() 方法相似,但有一些不同,
* 详情可见 与 Object.isExtensible() 的不同点。
* target
* 检查是否可扩展的目标对象。
* 返回一个 Boolean 值表明该对象是否可扩展。
* => boolean
*/
//Reflect.isExtensible(target)
const obj9 = {
name: 'obj9',
age: 9
};
Object.preventExtensions(obj9);
obj9.level = '1';
obj9.name = 'change';
const target9 = Reflect.isExtensible(obj9);
// console.log(obj9, target9);
//如果该方法的第一个参数不是一个对象(原始值),那么将造成一个 TypeError 异常。
//对于 Object.isExtensible(),非对象的第一个参数会被强制转换为一个对象。
/**
* Reflect.ownKeys()
* 静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。
* => keysArray
*/
//Reflect.ownKeys(target)
const obj10Prototype = {
level: 1
};
const obj10 = Object.create(obj10Prototype, {
name: {
value: 'obj10'
},
age: {
value: 10
}
});
const target10 = Reflect.ownKeys(obj10);
const targetO10 = Object.getOwnPropertyNames(obj10);
// console.log(target10, targetO10, obj10);
/**
* Reflect.preventExtensions()
* 静态方法 Reflect.preventExtensions() 方法阻止新属性添加到对象 (例如:防止将来对对象的扩展被添加到对象中)。
* 该方法与 Object.preventExtensions()相似,但有一些不同点。
* 返回一个 Boolean 值表明目标对象是否成功被设置为不可扩展。
* => boolean
*/
//Reflect.preventExtensions(target)
const obj11 = {
name: 'obj11',
age: 11
};
// const targetO11 = Object.preventExtensions(obj11)
// console.log(Object.isExtensible(obj11), targetO11);
const target11 = Reflect.preventExtensions(obj11);
// console.log(Object.isExtensible(obj11), Reflect.isExtensible(obj11), target11);
/**
* Reflect.set()
* 静态方法 Reflect.set() 工作方式就像在一个对象上设置一个属性。
* target
* 设置属性的目标对象。
* propertyKey
* 设置的属性的名称。
* value
* 设置的值。
* receiver
* 如果遇到 setter,receiver则为setter调用时的this值。
* 返回一个 Boolean 值表明是否成功设置属性。
* Reflect.set 方法允许你在对象上设置属性。
* 它的作用是给属性赋值并且就像 property accessor 语法一样,但是它是以函数的方式。
* => boolean
*/
//Reflect.set(target, propertyKey, value[, receiver])
const obj12 = {};
const target12 = Reflect.set(obj12);
// console.log(obj12, target12, Reflect.getOwnPropertyDescriptor(obj12));
/**
* Reflect.setPrototypeOf()
* 除了返回类型以外,
* 静态方法 Reflect.setPrototypeOf() 与 Object.setPrototypeOf() 方法是一样的。
* 它可设置对象的原型(即内部的 [[Prototype]] 属性)为另一个对象或 null,
* 如果操作成功返回 true,否则返回 false。
* target
* 设置原型的目标对象。
* prototype
* 对象的新原型(一个对象或 null)。
* =>boolean
*/
//Reflect.setPrototypeOf(target, prototype)
const obj13 = {
name: 'obj13',
age: 13
};
const obj13Prototype = {
level: 1
};
// const targetO13 = Object.setPrototypeOf(obj13, obj13Prototype);
// console.log(obj13Prototype.isPrototypeOf(obj13), targetO13);