Class 和 Function 之间存在一些差异 - 大多数人一开始会说 Class 是“只是语法糖”,但糖确实很重要。当 JS 解析器处理 JavaScript 代码时,解析器会将它们保存在不同的 AST 节点中,如下所示,ClassDeclaration 和 ClassExpression 在生成的 AST 树中是不同的节点类型:
https://github.com/estree/estree/blob/master/es2015.md#classes
您可以看到,对于这个解析器,新的 ES6 类规范在语法中引入了许多新的 AST 元素:
由于 AST 语法不是标准的,根据解析器的不同,可以有更多或更少的类型,但是需要注意的是,当代码进入类声明或类表达式时,JavaScript 引擎会以不同的方式解释它。
这意味着不能交换类和函数声明。如果您尝试编写,您可以看到这一点
class notWorking {
return 1; // <-- creates a parser error
};
这是因为当解析器遇到 class -keyword 时,它将开始将以下代码视为 ClassDeclaration 或 ClassExpression 的 ClassBody,然后它期望找到 MethodDefinitions。
这是一个小问题,因为创建私有变量变得更具挑战性。函数声明可以像这样巧妙地定义一个私有变量:
function myClass() {
var privateVar;
}
类声明不能有这个:
class myClass {
var privateVar; // ERROR: should be a method
}
这是因为类的语法只允许在类体内声明方法。至少现在。
但是,存在创建私有字段的建议:
https://github.com/zenparsing/es-private-fields
因此,将来你可能会说
class myClass {
#privateVar; // maybe this works in the future?
}
考虑到 ES6 类中的私有属性,有一个单独的答案,它建议了一些解决方法,例如使用符号:
Private properties in JavaScript ES6 classes
var property = Symbol(); // private property workaround example
class Something {
constructor(){
this[property] = "test";
}
}
类和函数之间自然有更多的区别。 其中之一是提升 1 - 与函数不同,您不能在范围内的任何地方声明类:
函数声明和类之间的重要区别
声明是函数声明被提升和类
声明不是。你首先需要声明你的类,然后
访问它
类声明和函数声明非常相似;
function foo1() {} // can be used before declaration
class foo2{} // new foo2(); works only after this declaration
类表达式的工作方式与函数表达式非常相似,例如它们可以分配给一个变量:
var myClass = class foobar {};
更多区别是1
- Class 表达式/声明主体始终以严格模式执行 - 无需手动指定
- 类有特殊的关键字constructor - 只能有一个,否则会抛出错误。函数可以有多个名为“构造函数”的函数变量的定义
- 类有特殊的关键字super,它与父类的构造函数有关。如果你在构造函数内部,你可以调用 super(x, y); 来调用父类构造函数,但是在 Method 内部你可以调用 super.foobar() 来创建调用任何父类函数。这种功能不适用于标准函数,尽管您可以通过一些自定义黑客来模拟它。
- 在类主体中,您可以使用 static 关键字定义函数,因此只能使用 ClassName.FunctionName() -syntax 来调用它。
- 类声明和表达式都可以使用 extends 关键字,例如 class Dog extends Animal
- MethodDeclaration 不需要函数前缀,因此您可以在类“m”中定义函数“ok”,如下所示:class m { ok() { } }。实际上甚至不允许将函数定义为 class m { function ok() { } }
然而,在解析器完成它的工作之后,类实例的运行方式基本上与任何其他对象相同。
新的 ES6 Class 语法本质上是用传统 OOP 方式表达对象的更清晰的方式,如果你喜欢它,那么你应该使用它。
编辑:此外,ES6 类语法还有另一个限制:它不允许成员函数使用粗箭头进行词法绑定。 ES7 似乎有 experimental feature 允许它。例如,当将方法绑定到事件处理程序时,这可能很有用,相关问题是here。
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes