Javascript 什么是反映。让我们来做这件事,不是';以前不可行吗?
我试图找到一个很好的理由来使用Javascript 什么是反映。让我们来做这件事,不是';以前不可行吗?,javascript,reflection,Javascript,Reflection,我试图找到一个很好的理由来使用Reflect.construct来实现一些我以前无法实现的值得注意的东西 我不是在寻找一个像这样的答案,因为这个例子似乎不是很有用。例如,我为什么要写作 function greetingFactory(name) { return Reflect.construct(Greeting, [name]); } 当我能写的时候 function greetingFactory(name) { return new Greeting(name); } ?
Reflect.construct
来实现一些我以前无法实现的值得注意的东西
我不是在寻找一个像这样的答案,因为这个例子似乎不是很有用。例如,我为什么要写作
function greetingFactory(name) {
return Reflect.construct(Greeting, [name]);
}
当我能写的时候
function greetingFactory(name) {
return new Greeting(name);
}
?
您知道Reflect.construct
的任何值得注意的用例吗
编辑:似乎我自己已经找到了一个用例,但我不确定它是否可靠,是否不会崩溃,但基本上我似乎可以使成为新的。target
通过如下方式编写ES5样式的类:
function Foo() {
console.log('Foo, new.target:', new.target)
this.name = "foo"
}
Foo.prototype.sayHello = function sayHello() {
return this.name
}
function Bar() {
console.log('Bar, new.target:', new.target)
let _ = Reflect.construct(Foo, [], new.target)
_.name = _.name + " bar"
return _
}
Bar.prototype = Object.create(Foo.prototype)
Bar.prototype.sayHello = function() {
return "Hello " + Foo.prototype.sayHello.call(this) + "!"
}
function Baz() {
console.log('Baz, new.target:', new.target)
let _ = Reflect.construct(Bar, [], new.target)
_.name = _.name + " baz"
return _
}
Baz.prototype = Object.create(Bar.prototype)
Baz.prototype.sayHello = function() {
return Bar.prototype.sayHello.call(this) + " Hello again!"
}
let baz = new Baz
console.log(baz.sayHello())
最酷的是,
这个
与原型方法中的预期一样 它接受其原型应在Reflect.constructor第三个参数中使用的构造函数。
尝试下面的代码并查看ArrayProto中的原型。
它将数组设置为构造函数,尽管开始时是Object/func1
函数func1(a、b、c){
这个。总和=a+b+c;
}
常量args=[1,2,3];
const object1=新的func1(…args);
const object2=Reflect.construct(func1,args);
const array1Proto=Reflect.construct(func1,args,Array);
console.log(object1)
console.log(object2)
console.log(arrayproto)
我一直在尝试整理Reflect.construct的一个有用的应用程序。我想我可能已经找到了一些东西,但如果我能从其他走上类似道路的人那里得到这个想法,那就太好了
我的想法是,您可以使用Reflect.construct
在实例化对象和预期对象之间插入[[Prototype]]
。这将允许您隐藏属于预期的[[Prototype]]
的属性和方法,而不会造成太大的干扰
function Wedge() {};
Wedge.prototype = Object.create(String.prototype);
Wedge.prototype.toUpperCase = function () {
return "nope";
}
let someString = Reflect.construct(String, ['Foo Bar'], Wedge)
someString.toUpperCase() // "nope"
据我所知,Reflect.construct的三个用例是:
在代理中使用它来获得默认行为(或获得稍微修改的默认行为)
使用它可以避免在需要使用数组调用构造函数时创建和使用迭代器,数组的元素需要作为离散参数传递。你可以这么做
但这涉及到创建和使用迭代器,而
t = Reflect.construct(Thing, theArray);
不使用迭代器,这样做的工作量要小得多(这并不重要;这适用于时间至关重要的情况)。(与迭代器不同,construct
只使用length
并直接访问0
、1
等属性。)
在ES2015之前,这两个选项都不可用。相反,您必须这样做:
t = Thing.apply(Object.create(Thing.prototype), theArray);
它与ES5构造函数一起工作。(它不适用于通过类创建的ES2015+构造函数,但您不需要它-您可以使用上述两个选项之一。)
在构造Error
或Array
的子类型或web组件的实例时,使用它可以避免使用类
(有些人,在可能需要传输的项目中,有很好的理由支持这一点)。(也就是说,Reflect.construct
也不可能是完美的多重填充。)
这个主题已经晚了,但实际上可以在ES5代码中正确地对本机类进行子类化。看起来是这样的:
function Foo() {
console.log('Foo, new.target:', new.target)
this.name = "foo"
}
Foo.prototype.sayHello = function sayHello() {
return this.name
}
function Bar() {
console.log('Bar, new.target:', new.target)
let _ = Reflect.construct(Foo, [], new.target)
_.name = _.name + " bar"
return _
}
Bar.prototype = Object.create(Foo.prototype)
Bar.prototype.sayHello = function() {
return "Hello " + Foo.prototype.sayHello.call(this) + "!"
}
function Baz() {
console.log('Baz, new.target:', new.target)
let _ = Reflect.construct(Bar, [], new.target)
_.name = _.name + " baz"
return _
}
Baz.prototype = Object.create(Bar.prototype)
Baz.prototype.sayHello = function() {
return Bar.prototype.sayHello.call(this) + " Hello again!"
}
let baz = new Baz
console.log(baz.sayHello())
//ES6类版本
类MyArray扩展了数组{
peek last(){
返回此[this.length-1];
}
}
//ES5类版本
函数MyArray(){
//不需要使用new,因为该实例已被丢弃
var retval=新数组();
retval.\uuuu proto\uuuuu=MyArray.prototype;//这是关键行
//在此处执行任何其他初始化以检索。
返回返回;
}
MyArray.prototype=Object.create(Array.prototype{
建造商:{
对,,
可写:对,
值:MyArray
},
最后一个:{
对,,
可写:对,
值:函数peekLast(){返回此[this.length-1];}
}
});
MyArray.\uuuuu proto\uuuuuu=数组;
我知道在ES6之前,\uuuuuu proto\uuuuuu
从未出现在ES标准中,但它实际上是所有主要浏览器和引擎都支持的web标准。这就是实现它的原因。我不认为这是为了实现以前不可能实现的事情,而是为这类“元”操作提供统一的API。@FelixKling我认为API作为更长的操作方式的快捷方式是有效的,但我想我也想知道,除了可能是一条捷径之外,Reflect.construct
是否解决了任何问题。@FelixKling我更新了答案,我想我可能已经找到了一个用例。“很酷的是,这与原型方法中的预期一样!”无论如何,这都是应该的,多亏了你对它们的调用方式。在上面使用Reflect.construct
所做的一切就是确保new.target
是为Bar
和Foo
的调用设置的(这可能确实有用;这基本上是my#3的一个通用版本)。这与使用Object.setPrototypeOf()手动设置原型有何不同
或obj.\uuuuuu proto\uuuuuu=…
有趣。对以下Reflect.construct
polyfill有什么想法@trusktr-从哪方面考虑?F.e.它有多完整,缺少哪些功能(F.e.无法多填充)?@trusktr-在纯ES5环境中。,您无法正确地将Error
或Array
子类化,因此使用Reflect。当您提供新的时,使用Error
或Array
构造。target
(第三个参数)不起作用(也不能)。在具有\uuuu proto\uuuu
的ES5环境中(Firefox中的SpiderMonkey可以追溯到几年前,IE11中的Chakra),您可以,但特定的polyfill不会尝试这样做。不是批评