我正在努力找到一个很好的理由来使用Reflect.construct
来实现我以前无法实现的值得注意的东西。
我不是在寻找像one here这样的答案,因为这个例子看起来并不是很有用。例如,我为什么要写
function greetingFactory(name) {
return Reflect.construct(Greeting, [name]);
}
我什么时候可以写
function greetingFactory(name) {
return new Greeting(name);
}
您是否知道Reflect.construct
的任何显着用例?
new.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())
关于它的一个很酷的事情是this
在原型方法中是预期的!
答案 0 :(得分:1)
它接受应该在第三个参数 Reflect.constructor 中使用其原型的构造函数。 请在下面尝试以下代码,并查看 array1Proto 中的原型。 尽管开头是Object / func1,但仍将Array设置为构造函数。
function func1(a, b, c) {
this.sum = a + b + c;
}
const args = [1, 2, 3];
const object1 = new func1(...args);
const object2 = Reflect.construct(func1, args);
const array1Proto = Reflect.construct(func1, args, Array);
console.log(object1)
console.log(object2)
console.log(array1Proto)
答案 1 :(得分:1)
我也一直在尝试整理Reflect.construct
的有用应用程序。我想我可能已经找到了一些东西,但是最好还是以类似的方式将这个想法与其他人联系起来。
我在想的是,您可以使用Reflect.construct
在实例化的对象和预期的[[Prototype]]
之间楔入一个[[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"
答案 2 :(得分:1)
我知道的Reflect.construct
仅有三个用例是:
在代理服务器construct
trap中使用它来获取默认行为(或获取经过稍微修改的默认行为)。
在需要使用需要将元素作为离散参数传递的数组调用构造函数时,使用它来避免创建和使用迭代器。您可以可以做
t = new Thing(...theArray);
但是涉及创建和使用迭代器,而
t = Reflect.construct(Thing, theArray);
不使用迭代器,它的工作量要少得多(通常并不重要;这是在您知道时间至关重要的情况下)。 (construct
只使用length
而不是迭代器,而是直接访问0
,1
等属性。)
ES2015之前这些选项都不可用。相反,您必须这样做:
t = Thing.apply(Object.create(Thing.prototype), theArray);
与ES5构造函数一起使用。 (它不适用于通过class
创建的ES2015 +构造函数,但您不需要它-您可以使用上面两个选项之一。)
在构造class
或Error
或Web组件(某些人don't like to use class
等)的子类型的实例时,应避免使用Array
在可能需要转译的项目中是很好的论据)。 (也就是说,Reflect.construct
也不能完美地填充。)
答案 3 :(得分:1)
这个话题还很晚,但是实际上可以在ES5代码中适当地子类化本机类。看起来像这样:
//ES6-class version
class MyArray extends Array {
peekLast() {
return this[this.length - 1];
}
}
//ES5-class version
function MyArray() {
//No need to use new since that instance gets discarded
var retval = new Array();
retval.__proto__ = MyArray.prototype; //This is the key line
//Do any other initialization to retval here.
return retval;
}
MyArray.prototype = Object.create(Array.prototype, {
constructor: {
configurable: true,
writable: true,
value: MyArray
},
peekLast: {
configurable: true,
writable: true,
value: function peekLast() { return this[this.length - 1]; }
}
});
MyArray.__proto__ = Array;
我知道__proto__
在ES6之前从未出现在ES标准中,但这是所有主要浏览器和引擎都支持的事实上的Web标准。这就是使之成为可能的原因。