Javascript:函数和类有什么区别 [英] Javascript: What is the difference between Function and Class

查看:41
本文介绍了Javascript:函数和类有什么区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

随着 2015 年 6 月 ECMAScript 6 的发布,引入了 Javascript 类语法.

With the release of ECMAScript 6 on June 2015, Javascript classes syntax was introduced.

这个语法:

class Polygon {
      constructor(width, height) {
        this.width = width;
        this.height = height;
      }
}

基本相同:

function Polygon(width, height) {
    this.width = width;
    this.height = height;
}

那么使用类代替传统函数有什么好处呢?在什么情况下我应该使用类而不是函数?

So what is the benefit of using class instead of traditional function? And in what condition I should use class instead of function?

推荐答案

Class 和 Function 之间有一些区别 - 大多数人一开始会说 Class 是只是语法糖",但糖确实很重要.当 JS 解析器处理 JavaScript 代码时,解析器会将它们保存在不同的 AST 节点中,如下所示,ClassDeclarationClassExpression 在生成的 AST 树中是不同的节点类型:

There are some differences between Class and Function - most people will start by saying that the Class is "just syntax sugar", but that sugar does matter quite a bit. When the JS parser is processing the JavaScript code the parser will save them in different AST nodes, like shown here the ClassDeclaration and ClassExpression are different node types in the resulting AST tree:

https://github.com/estree/estree/blob/master/es2015.md#classes

你可以看到,对于这个解析器,新的 ES6 Classes 规范在语法中引入了许多新的 AST 元素:

You can see that for this parser, the new ES6 Classes spec introduces a number of new AST elements to the syntax:

  • 类体
  • 方法定义
  • 类声明
  • 类表达式
  • 元属性

由于 AST 语法不是标准的,可能有更多或更少的类型,具体取决于解析器,但需要注意的是,当代码进入类声明或类表达式时,JavaScript 引擎会对其进行不同的解释.

Since the AST syntax is not standard, there can be more or less types depending on the parser, but what is important to notice that when the code enters the class declaration or class expression it will be interpreted differently by the JavaScript engine.

这意味着不能交换类和函数声明.如果您尝试编写,您可以看到这一点

This means, that Class and Function declarations can not be exchanged. You can see this if you try to write

class notWorking {
  return 1;  // <-- creates a parser error
};

这是因为当解析器遇到 class 关键字时,它会开始将以下代码视为 ClassDeclaration 或 ClassExpression 的 ClassBody,然后期望找到 MethodDefinitions.

This is because when the parser encounters the class -keyword, it will start treating the following code as ClassBody of either ClassDeclaration or ClassExpression and then it expects to find MethodDefinitions.

这是一个小问题,因为创建私有变量变得有点困难.函数声明可以像这样巧妙地定义一个私有变量:

This is a small problem, because creating private variables becomes a bit more challenging. The function declaration could define a private variable neatly like this:

function myClass() {
    var privateVar;
}

类声明不能有这个:

class myClass {
    var privateVar; // ERROR: should be a method
}

这是因为类的语法只允许在类体内声明方法.至少现在.

This is because the syntax of class allows only methods to be declared inside the class body. At least right now.

但是,存在创建私有字段的提议:

However, there exists a proposal for creating private fields:

https://github.com/zenparsing/es-private-fields

因此,将来你可能会说

class myClass {
   #privateVar; // maybe this works in the future?
}

考虑到 ES6 类中的私有属性,有一个单独的答案,它建议了一些解决方法,例如使用符号:

There is a separate answer considering the private properties in ES6 Classes, which is suggesting some workarounds, like the use of Symbols:

JavaScript ES6 类中的私有属性

var property = Symbol(); // private property workaround example
class Something {
    constructor(){
        this[property] = "test";
    }
}

当然,类和函数之间存在更多差异.其中之一是提升 1 - 与函数不同,你不能在作用域内的任何地方声明类:

Naturally there are more differences between classes and functions. One of them is Hoisting 1 - unlike Functions, you can't declare the Class anywhere in the scope:

函数声明和类的重要区别声明是函数声明被提升和类声明不是.你首先需要声明你的类,然后访问它

An important difference between function declarations and class declarations is that function declarations are hoisted and class declarations are not. You first need to declare your class and then access it

类声明和函数声明非常相似;

The Class declarations and Function declarations are quite similar;

function foo1() {} // can be used before declaration
class  foo2{}      // new foo2(); works only after this declaration

类表达式的工作方式与函数表达式非常相似,例如它们可以分配给变量:

The class expressions work quite similarly to function expressions, for example they can be assigned to a variable:

var myClass = class foobar {};

更多区别是1

  1. Class 表达式/声明体总是以严格模式执行——无需手动指定
  2. 类有特殊的关键字constructor - 只能有一个,否则会抛出错误.函数可以有多个名为构造函数"的函数变量定义
  3. 类具有与父类构造函数相关的特殊关键字super.如果您在构造函数内部,您可以调用 super(x, y); 来调用父类构造函数,但在 Method 内部,您可以调用 super.foobar() 来创建调用任何父类函数.这种功能不适用于标准函数,尽管您可以通过一些自定义黑客来模拟它.
  4. 在类体内,您可以使用 static 关键字定义函数,因此可以仅使用 ClassName.FunctionName() -syntax 来调用它.
  5. 类声明和表达式都可以使用extends关键字,如class Dog extends Animal
  6. MethodDeclaration 不需要函数前缀,因此您可以像这样在类m"中定义函数ok":class m { ok() { } }.实际上甚至不允许将函数定义为 class m { function ok() { } }
  1. The Class expression / declaration body is always executed in Strict mode - no need to specify that manually
  2. Classes have special keyword constructor - there can be only one of them, or error is thrown. Functions could have multiple definitions of variable of function named "constructor"
  3. Classes have special keyword super which relates to the parent classes constructor. If you are inside the constructor you can call super(x, y); to call the parent class constructor but inside the Method you can call super.foobar() to create call to any parent class function. This kind of functionality is not available for standard Functions although you might emulate it with some custom hacking.
  4. Inside class body you can define function with static keyword so it can be called using only ClassName.FunctionName() -syntax.
  5. Both class declarations and expressions can use extends keyword like class Dog extends Animal
  6. MethodDeclaration does not need function -prefix, thus you can define function "ok" inside the class "m" like this: class m { ok() { } }. Actually it is not even allowed to define function as class m { function ok() { } }

然而,在解析器完成其工作后,类实例的运行方式基本上与任何其他对象相同.

However, after the parser has completed it's job, the class instance is essentially running the same way as any other object.

新的 ES6 Class 语法本质上是更清晰的以传统 OOP 方式表达对象的方式,如果你喜欢它,那么你应该使用它.

The new ES6 Class syntax is essentially more clear way of expressing objects in a traditional OOP way and if you like it, then you should use it.

此外,ES6 类语法还有另一个限制:它不允许成员函数使用使用粗箭头进行词法绑定.ES7 似乎有 实验功能 允许它.例如,在将方法绑定到事件处理程序时,这可能很有用,相关问题是 此处.

also, the ES6 Class syntax has also another limitation: it does not allow the member functions to use lexically binded using fat arrow. ES7 seems to have experimental feature allowing it. That can be useful for example when binding methods to event handlers, the related question is here.

1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/类

这篇关于Javascript:函数和类有什么区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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