2015年更新:
正如第7条回答所指出的那样,既然ES6(ECMAScript 2015)已经完成,现在可以找到更多合适的文档:
原始答案(用于(历史性)理解和更多示例):
在Reflection proposal似乎已经进展到草案的ECMAScript 6规范。本文档当前概述了Reflect-object的方法,并且仅说明了Reflect-object本身的以下内容:
Reflect对象是单个普通对象。
Reflect对象的[[Prototype]]内部插槽的值是标准的内置Object原型对象(19.1.3)。
Reflect对象不是函数对象。它没有[[Construct]]内部方法。不能将Reflect对象与new运算符一起用作构造函数。Reflect对象也没有[[Call]]内部方法。不能将Reflect对象作为函数调用。
但是,在ES Harmony中有一个简短的解释:
“ @reflect”模块有多种用途:
- 现在我们有了模块,对于以前在Object上定义的许多反射方法,“ @ reflect”模块更为自然。出于向后兼容的目的,Object上的静态方法不太可能消失。但是,应该将新方法添加到“ @reflect”模块,而不是对象构造函数。
- 代理的天然家园,无需全局代理绑定。
- 此模块中的大多数方法都将一对一映射到代理陷阱。代理处理程序需要这些方法来方便地转发操作,如下所示。
因此,该Reflect对象提供了许多实用程序功能,其中许多功能似乎与在全局对象上定义的ES5方法重叠。
但是,这并不能真正解释它打算解决哪些现有问题或添加了什么功能。我怀疑这可能是不正确的,并且实际上,上述和谐规范链接到“这些方法的非规范,近似实现”。
检查该代码可以使人们对它的使用有更进一步的了解,但值得庆幸的是,还有一个Wiki概述了Reflect对象有用的许多原因:(
我已经复制(并格式化)了以下文本,以供以后参考资料来源,因为它们是我唯一能找到的例子。除此之外,它们很有意义,已经有了很好的解释,并可以回答问题的apply例子。)
更有用的返回值
许多操作在Reflect类似于定义ES5操作Object,比如Reflect.getOwnPropertyDescriptor和Reflect.defineProperty。但是,虽然Object.defineProperty(obj, name, desc)将obj在成功定义属性时返回,否则将抛出TypeError否则,但Reflect.defineProperty(obj, name, desc)仅返回一个布尔值即可,该布尔值指示属性是否已成功定义。这使您可以重构以下代码:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
对此:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
返回此类布尔成功状态的其他方法是Reflect.set(更新属性),Reflect.deleteProperty(删除属性),Reflect.preventExtensions(使对象不可扩展)和Reflect.setPrototypeOf(更新对象的原型链接)。
一流的运营
在ES5中,检测对象是否obj定义或继承某个属性名称的方法是write (name in obj)。同样,要删除属性,请使用delete obj[name]。尽管专用语法既好又简短,但这也意味着当您要将这些操作作为一等值传递时,必须将这些操作显式包装在函数中。
使用Reflect,这些操作很容易被定义为一等函数:
Reflect.has(obj, name)是等价的函数,(name in obj)并且Reflect.deleteProperty(obj, name)是与以下函数相同的函数delete obj[name].
更可靠的功能应用
在ES5中,当要调用一个函数时f,将可变数量的参数打包为一个数组args并将this值绑定到obj,则可以编写:
f.apply(obj, args)
但是,f可能是有意或无意定义其自身apply方法的对象。当您确实要确保apply调用内置函数时,通常会这样写:
Function.prototype.apply.call(f, obj, args)
这不仅冗长,而且很快变得难以理解。使用Reflect,您现在可以以更短且更容易理解的方式进行可靠的函数调用:
Reflect.apply(f, obj, args)
可变参数构造函数
假设您要使用可变数量的参数调用构造函数。在ES6中,由于采用了新的传播语法,因此可以编写如下代码:
var obj = new F(...args)
在ES5,这是更难写,因为一次只能使用F.apply或F.call调用函数的参数个数可变,但没有F.construct对功能new与参数个数可变的功能。使用Reflect,现在可以在ES5中编写:
var obj = Reflect.construct(F, args)
代理陷阱的默认转发行为
当使用Proxy对象包装现有对象时,通常会先截取一个操作,执行某些操作,然后“执行默认操作”,这通常是将截取的操作应用于包装的对象。例如,假设我只想记录对对象的所有属性访问obj:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
在Reflect和ProxyAPI的设计串联,使得对于每个Proxy陷阱,存在一个相应的方法上Reflect说,“确实默认的事情”。因此,每当您发现自己想要在Proxy处理程序中“执行默认操作”时,正确的操作是始终在Reflect对象中调用相应的方法:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
的返回类型Reflect的方法是保证用的返回类型兼容的Proxy陷阱。
控制访问者的此绑定
在ES5中,进行常规属性访问或属性更新相当容易。例如:
var name = ...
obj[name]
obj[name] = value
该Reflect.get和Reflect.set方法允许你做同样的事情,而且还接受作为最后的可选参数一个receiver参数,使您可以明确设置this属性时,你得到结合位/集是访问:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
这在包装时偶尔有用,obj并且希望访问器中的任何自发送都重新路由到包装器,例如,如果obj定义为:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
呼叫Reflect.get(obj, "foo", wrapper)将导致this.bar()呼叫转接到wrapper。
避免遗留 __proto__
在某些浏览器中,__proto__定义为允许访问对象原型的特殊属性。ES5标准化了一种Object.getPrototypeOf(obj)查询原型的新方法。Reflect.getPrototypeOf(obj)的功能完全相同,只是Reflect它还定义了一个对应Reflect.setPrototypeOf(obj, newProto)的设置对象的原型。这是更新对象原型的符合ES6的新方法。
注意:setPrototypeOf 也存在Object(如Knu的注释正确指出的)!
编辑:
旁注(解决对Q的评论):关于“ Q:ES6模块与HTML导入”的解释Realms和Loader对象有一个简短的答案。
该链接提供了另一种解释:
领域对象通过其自己的全局对象,标准库的副本和“ intrinsics”(未绑定至全局变量的标准对象,如Object.prototype的初始值)抽象出独特的全局环境的概念。
可扩展的网络:这是<iframe>没有DOM的动态同源
。
值得一提的是:这一切仍在草案中,这不是刻板的规范!它是ES6,因此请牢记浏览器的兼容性!
希望这可以帮助!
Reflect它只是Realm和Loader对象的容器,但我也不知道后者做什么。