如何检查Javascript函数是否为构造函数 [英] How to check if a Javascript function is a constructor

查看:212
本文介绍了如何检查Javascript函数是否为构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到并非所有的Javascript函数都是构造函数。

I noticed not all the Javascript functions are constructors.

var obj = Function.prototype;
console.log(typeof obj === 'function'); //true
obj(); //OK
new obj(); //TypeError: obj is not a constructor

问题1:如何检查函数是否为a构造函数,以便可以使用new调用它?

Question 1: How do I check if a function is a constructor so that it can be called with a new?

问题2:当我创建一个函数时,是否可以使它 a构造函数?

Question 2: When I create a function, is it possible to make it NOT a constructor?

推荐答案

一点背景知识:

ECMAScript 6 +区分 callable (可以不带 new 调用)和可构造(可以用 new )函数:

ECMAScript 6+ distinguishes between callable (can be called without new) and constructable (can be called with new) functions:


  • 通过箭头函数语法或类或对象中的方法定义创建的函数文字不可构造

  • 通过语法创建的函数不可调用

  • 以任何其他方式创建的函数(函数表达式/声明,函数构造函数)是可调用和可构造的。

  • 内置函数是除非明确说明,否则不可构建。

  • Functions created via the arrow functions syntax or via a method definition in classes or object literals are not constructable.
  • Functions created via the class syntax are not callable.
  • Functions created in any other way (function expression/declaration, Function constructor) are callable and constructable.
  • Built-in functions are not constructrable unless explicitly stated otherwise.

关于 Function.prototype

About Function.prototype

Function.prototype 是一个所谓的 内置函数 不可构建。来自规范:

Function.prototype is a so called built-in function that is not constructable. From the spec:


未标识为构造函数的内置函数对象未实现 [[Construct] ]] 内部方法,除非在特定函数的描述中另有说明。

Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.

Function.prototype 的值是在最开始时创建的运行时初始化它基本上是一个空函数,并没有明确说明它是可构造的。

The value of Function.prototype is create at the very beginning of the runtime initialization. It is basically an empty function and it is not explicitly stated that it is constructable.


如何检查函数是否为构造函数,以便可以使用new调用它?

How do I check if an function is a constructor so that it can be called with a new?

没有内置的方法可以做到这一点。您可以尝试使用 new 调用该函数,并检查错误或返回 true

There isn't a built-in way to do that. You can try to call the function with new, and either inspect the error or return true:

function isConstructor(f) {
  try {
    new f();
  } catch (err) {
    // verify err is the expected error and then
    return false;
  }
  return true;
}

然而,这种方法不是故障保护,因为功能可能有副作用,所以调用 f ,你不知道环境处于哪种状态。

However, that approach is not failsafe since functions can have side effects, so after calling f, you don't know which state the environment is in.

此外,这只会告诉你函数是否可以作为构造函数调用,而不是意图作为构造函数调用。为此,你必须查看文档或函数的实现。

Also, this will only tell you whether a function can be called as a constructor, not if it is intended to be called as constructor. For that you have to look at the documentation or the implementation of the function.

注意:永远不应该有理由使用测试像生产环境中的这个。是否应该使用 new 调用函数应该可以从其文档中辨别出来。

Note: There should never be a reason to use a test like this one in a production environment. Whether or not a function is supposed to be called with new should be discernable from its documentation.


当我创建一个函数时,如何使它不是构造函数?

When I create a function, how do I make it NOT a constructor?

要创建一个真正不是可构造的的函数,你可以使用箭头函数:

To create a function is truly not constructable, you can use an arrow function:

var f = () => console.log('no constructable');

箭头函数根据定义是不可构造的。或者,您可以将函数定义为对象或类的方法。

Arrow functions are by definition not constructable. Alternatively you could define a function as a method of an object or a class.

否则,您可以检查是否使用 new调用函数(或类似的东西)通过检查它的这个值并抛出错误,如果是:

Otherwise you could check whether a function is called with new (or something similar) by checking it's this value and throw an error if it is:

function foo() {
  if (this instanceof foo) {
    throw new Error("Don't call 'foo' with new");
  }
}

当然,因为还有其他方法来设置值,可能存在误报。

Of course, since there are other ways to set the value of this, there can be false positives.

示例

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()');

这篇关于如何检查Javascript函数是否为构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆