Reflect

Reflect 对象提供了若干个能对任意对象进行某种特定的可拦截操作(interceptable operation)的方法。

描述

一个全局的对象,虽然首字母是大写的,但是并不表示它是一个构造函数,所以不能用new运算符来初始化“Reflect对象”,它的所有方法都是静态的。有点类似于Math。

方法

Reflect.apply

对一个函数进行调用操作,关键在于其指定了特定的this对象。使用方法为:

Reflect.apply(fun, target, argvs);

和我们熟知的fun.apply(target,argvs)效果是一样的,使用Reflect更加简洁易懂。 注意:argvs必须是数组或者类似数组的对象。

Reflect.construct

对构造函数进行初始化,类似于new Xxx()的操作。

var date = Reflect.construct(Date,[2016,7,17]);
等同于
var date = new Date(2016,7,17);

该方法有第三个参数,用于修改new.target

function someConstructor() {}
var result = Reflect.construct(Array, [], someConstructor);

Reflect.getPrototypeOf(result); // 输出:someConstructor.prototype
Array.isArray(result); // true
可以理解把对象的prototype修改成第三个参数的prototype

function Foo(arg){this.name = arg+'foo';}
function Bar(arg){this.age = arg+'bar';}
Bar.prototype.show = function(){
    console.log(this.age);
}
var result = Reflect.construct(Foo, ['test'], Bar);
result.age // ?
result.name // ?
result.show() // ?
result.constructor // ?

Reflect.defineProperty

为对象定义属性和值

var obj = {};
Reflect.defineProperty(obj, "x", {value: 7}); // true
obj.x; // 7
Reflect.defineProperty(obj, "x", {value: 8}); // false

类似于Object.defineProperty(),但是会有一个boolean的返回值,表示该值是否被成功定义,而Object.defineProperty()会返回对象或报错

Reflect.deleteProperty

删除对象的某个属性

var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }

类似于delete obj[xx],返回boolean值表示是否删除成功

Reflect.enumerate

该方法会返回一个包含有目标对象身上所有可枚举的自身字符串属性以及继承字符串属性的迭代器,for...in 操作遍历到的正是这些属性。

var obj = { x: 1, y: 2 };

for (var name of Reflect.enumerate(obj)) {
  console.log(name);
}

注意:已弃用

Reflect.get

获取对象身上某个属性的值。

// Object
var obj = { x: 1, y: 2 };
Reflect.get(obj, "x"); // 1
// Array
Reflect.get(["zero", "one"], 1); // "one"

类似于我们经常使用的获取对象属性的target[name]

Reflect.set

设置对象身上某个属性的值。

// Object
var obj = {};
Reflect.set(obj, "prop", "value"); // true
obj.prop; // "value"

// Array
var arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
arr[2]; // "goose"

// 参数只有一个的时候,并不会报错,但是key和value都是undefined
var obj = {};
Reflect.set(obj); // true
Reflect.getOwnPropertyDescriptor(obj, "undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }

类似于target.name = xxx;

Reflect.getOwnPropertyDescriptor

返回对象中属性的描述,如果对象中不存在该属性的话,返回undefined

Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");
// {value: "hello", writable: true, enumerable: true, configurable: true}

类似于Object.getOwnPropertyDescriptor()

Reflect.getPrototypeOf

获取一个对象原型上的属性

Reflect.getPrototypeOf({}); // Object.prototype
var date = new Date();
Reflect.getPrototypeOf(date) === Date.prototype; // true

类似于Object.getPrototypeOf()

Reflect.setPrototypeOf

设置对象的原型属性或置空

Reflect.setPrototypeOf({}, Object.prototype); // true

// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null); // false

类似于Object.setPrototypeOf()

Reflect.has

判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。

Reflect.has({x: 0}, "x"); // true
Reflect.has({x: 0}, "y"); // false

Reflect.isExtensible

判断一个对象是否是可扩展的,即是否可以增加新的属性。

var empty = {};
Reflect.isExtensible(empty); // === true 

Reflect.preventExtensions(empty); 
Reflect.isExtensible(empty); // === false 

var sealed = Object.seal({}); 
Reflect.isExtensible(sealed); // === false 

var frozen = Object.freeze({}); 
Reflect.isExtensible(frozen); // === false

类似于Object.isExtensible(),但是有一点点不同,Reflect.isExtensible的第一个参数必须是对象,否则会报错,而Object.isExtensible()并没有这个限制。

Reflect.isExtensible(1);
// TypeError: 1 is not an object

Object.isExtensible(1);
// false

Reflect.preventExtensions

不允许再在对象上新增属性值。用法见Reflect.isExtensible。 类似于Object.preventExtensions,但是也有不同点,即必须传递对象参数。

Reflect.ownKeys

返回一个包含所有自身属性(不包含继承属性)的数组。

Reflect.ownKeys({z: 3, y: 2, x: 1}); 
// [ "z", "y", "x" ]

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);
// [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]

类似于Object.getOwnPropertyNames,但是更加强大,相当于

Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)).

总结

Reflect比较简单,并没有特别新的东西,只是对原来就有的内容做了些修改(貌似是的)。这样设计的目的是什么?