背景的一点点:创建
关于Function.prototype
Function.prototype
是所谓的built-in functionthat is not constructable。从规格:
未标识为构造函数的内置函数对象不实现[[Construct]]
内部方法,除非在特定函数的说明中另有说明。
Function.prototype
的值是在运行时初始化时创建的。它基本上是一个空的函数,并没有明确说明它是可以构造的。
我如何检查如果一个函数是一个构造函数,以便它可以用一个新的被称为?
有没有一种内置的方式来做到这一点。您可以try
调用函数new
,并且或者检查错误或返回true
:
function isConstructor(f) {
try {
new f();
} catch (err) {
// verify err is the expected error and then
return false;
}
return true;
}
然而,这种做法是不是失效保护功能,因为可以有副作用,因此调用f
后,你不知道环境所处的状态。
而且,这只会告诉你是否一个功能可以被称为构造函数,而不是是否是打算被称为构造函数。为此,您必须查看文档或函数的实现。
注意:在生产环境中不应该有像这样的测试。从文档中可以看出,是否应该使用new
来调用某个函数。
当我创建一个函数时,如何使它不是构造函数?
要创建一个功能是真正的不施工的,你可以用一个箭头功能:
var f =() => console.log('no constructable');
箭头功能被定义不施工的。或者,您可以将函数定义为对象或类的方法。
否则,你可以检查一个函数是否被调用,new
(或类似的东西)通过检查它的this
价值,如果它是抛出一个错误:
function foo() {
if (this instanceof foo) {
throw new Error("Don't call 'foo' with new");
}
}
当然,因为有其他的方式来设置值为this
,可能有误报。
例子
function isConstructor(f) {
try {
new f();
} catch (err) {
if (err.message.indexOf('is not a constructor') >= 0) {
return false;
}
}
return true;
}
function test(f, name) {
console.log(`${name} is constructable: ${isConstructor(f)}`);
}
function foo(){}
test(foo, 'function declaration');
test(function(){}, 'function expression');
test(()=>{}, 'arrow function');
class Foo {}
test(Foo, 'class declaration');
test(class {}, 'class expression');
test({foo(){}}.foo, 'object method');
class Foo2 {
static bar() {}
bar() {}
}
test(Foo2.bar, 'static class method');
test(new Foo2().bar, 'class method');
test(new Function(), 'new Function()');
有趣的是'Function'和'Function.prototype'是唯一不是构造函数的函数吗? – Adam
功能是一个construtor。新函数();作品。 –
只需检查该类型是否为函数。 – rlemon