Javascript 如何检查变量是否是 ES6 类声明?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30758961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a variable is an ES6 class declaration?
提问by X?pplI'-I0llwlg'I -
I am exporting the following ES6 class from one module:
我正在从一个模块导出以下 ES6 类:
export class Thingy {
hello() {
console.log("A");
}
world() {
console.log("B");
}
}
And importing it from another module:
并从另一个模块导入它:
import {Thingy} from "thingy";
if (isClass(Thingy)) {
// Do something...
}
How can I check whether a variable is a class? Not a class instance, but a class declaration?
如何检查变量是否是类?不是类实例,而是类声明?
In other words, how would I implement the isClassfunction in the example above?
换句话说,我将如何实现isClass上面示例中的功能?
采纳答案by loganfsmyth
I'll make it clear up front here, any arbitrary function can be a constructor. If you are distinguishing between "class" and "function", you are making poor API design choices. If you assume something must be a classfor instance, no-one using Babel or Typescript will be be detected as a classbecause their code will have been converted to a function instead. It means you are mandating that anyone using your codebase mustbe running in an ES6 environment in general, so your code will be unusable on older environments.
我会在这里先说清楚,任何任意函数都可以是构造函数。如果您要区分“类”和“函数”,那么您就做出了糟糕的 API 设计选择。class例如,如果您假设某些东西必须是 a ,则不会将使用 Babel 或 Typescript 的任何人检测为 a,class因为它们的代码已被转换为函数。这意味着您要求使用您的代码库的任何人通常都必须在 ES6 环境中运行,因此您的代码将无法在旧环境中使用。
Your options here are limited to implementation-defined behavior. In ES6, once code is parsed and the syntax is processed, there isn't much class-specific behavior left. All you have is a constructor function. Your best choice is to do
您在此处的选择仅限于实现定义的行为。在 ES6 中,一旦解析了代码并处理了语法,就没有多少特定于类的行为了。你所拥有的只是一个构造函数。你最好的选择是做
if (typeof Thingy === 'function'){
// It's a function, so it definitely can't be an instance.
} else {
// It could be anything other than a constructor
}
and if someone needs to do a non-constructor function, expose a separate API for that.
如果有人需要执行非构造函数,请为此公开一个单独的 API。
Obviously that is not the answer you are looking for, but it's important to make that clear.
显然,这不是您要寻找的答案,但明确这一点很重要。
As the other answer here mentions, you do have an option because .toString()on functions is required to return a class declaration, e.g.
正如这里的另一个答案所提到的,您确实有一个选择,因为.toString()函数需要返回类声明,例如
class Foo {}
Foo.toString() === "class Foo {}" // true
The key thing, however, is that that only applies if it can. It is 100% spec compliant for an implementation to have
然而,关键是只有在可以的情况下才适用。实现 100% 符合规范
class Foo{}
Foo.toString() === "throw SyntaxError();"
No browserscurrently do that, but there are several embedded systems that focus on JS programming for instance, and to preserve memory for your program itself, they discard the source code once it has been parsed, meaning they will have no source code to return from .toString()and that is allowed.
目前没有浏览器这样做,但有几个嵌入式系统专注于 JS 编程,例如,为了保护程序本身的内存,它们在解析后丢弃源代码,这意味着它们将没有源代码可返回.toString()这是允许的。
Similarly, by using .toString()you are making assumptions about both future-proofing, and general API design. Say you do
同样,通过使用,.toString()您正在对面向未来和通用 API 设计做出假设。说你做
const isClass = fn => /^\s*class/.test(fn.toString());
because this relies on string representations, it could easily break.
因为这依赖于字符串表示,所以它很容易被破坏。
Take decorators for example:
以装饰器为例:
@decorator class Foo {}
Foo.toString() == ???
Does the .toString()of this include the decorator? What if the decorator itself returns a functioninstead of a class?
请问.toString()这包括装饰?如果装饰器本身返回一个function而不是一个类呢?
回答by Felix Kling
If you want to ensure that the value is not only a function, but really a constructor function for a class, you can convert the function to a string and inspect its representation. The spec dictates the string representation of a class constructor.
如果您想确保该值不仅是一个函数,而且确实是一个类的构造函数,您可以将该函数转换为字符串并检查其表示形式。规范规定了类构造函数的字符串表示形式。
function isClass(v) {
return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
}
Another solution would be to try to call the value as a normal function. Class constructors are not callable as normal functions, but error messages probably vary between browsers:
另一种解决方案是尝试将该值作为普通函数调用。类构造函数不能作为普通函数调用,但错误消息可能因浏览器而异:
function isClass(v) {
if (typeof v !== 'function') {
return false;
}
try {
v();
return false;
} catch(error) {
if (/^Class constructor/.test(error.message)) {
return true;
}
return false;
}
}
The disadvantage is that invoking the function can have all kinds of unknown side effects...
缺点是调用函数会产生各种未知的副作用……
回答by aimadnet
Maybe this can help
也许这可以帮助
let is_class = (obj) => {
try {
new obj();
return true;
} catch(e) {
return false;
};
};
回答by Mat
What about:
关于什么:
function isClass(v) {
return typeof v === 'function' && v.prototype.constructor === v;
}

