我正在阅读ECMAScript 2015 new.target属性。我觉得这很有意思,我可以使用new运算符配置一个函数,然后通过普通调用来调用它。但由于某种原因,这似乎不起作用。这是我的测试代码。
function Test(newConfig) {
if(new.target){
if(Test2 !== undefined){
console.log(new.target === Test2);// why does this give false
console.log(new.target === Test);// why does this give true
}
let mergedConfig = {};
Object.assign(mergedConfig, newConfig || {}, new.target.config || {})
let fn = Test.bind({config: mergedConfig});
fn.config = mergedConfig;
return fn;
} else {
// do something with this.config
return this.config.a + this.config.b;
}
}
// initial configuration
// the first time I'm calling the Test function, so new.target === Test
var Test2 = new Test({
a: 'a'
});
// further configuration
// the second time I'm calling the Test2 function.
// Now, new.target !== Test2, but new.target === Test.
// This is what seems weird to me.
let Test3 = new Test2({b: 'b'});
// normal call
// new.target === undefined
let result = Test3();
答案 0 :(得分:2)
new.target
并不总是引用被调用的函数。相反,它引用了.prototype
属性应该用作新实例的原型的函数(以便超类可以创建正确的东西)。
.bind()
方法确实创建了特殊的"绑定函数"对象的唯一目的是使用提供的this
值和部分应用的参数列表调用原始函数。他们甚至没有.prototype
财产 - 这应该明确表明它们不是new.target
的合适值。事实上,他们的[[construct]] method被指定使用原始函数代替绑定函数。
那你该怎么办?当然,"使用new
配置功能"应该避免在生产代码中,但它是一个很好的实验。我建议在这里避免使用bind
,而是使用闭包:
function makeTest(config) {
return function ConfiguredTest(newConfig) {
if (new.target) {
let mergedConfig = {};
Object.assign(mergedConfig, newConfig || {}, config) // I presume you want to swap the latter two
return makeTest(mergedConfig);
} else {
// use `config` here
return config.a + config.b;
}
};
}
const Test = makeTest({});
// like before
let Test2 = new Test(…)
let Test3 = new Test2(…)
Test3()