Javascript:功能与类之间有什么区别? [英] Javascript: What is the difference between Function and Class

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

问题描述



这个语法:

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

基本相同:

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

那么使用类而不是传统函数有什么好处?
在什么条件下我应该使用类而不是函数?

解决方案

类和函数之间有一些区别 - 大多数人都会开始说这个课是只是语法糖,但是糖确实很重要。当JS解析器正在开发JavaScript代码时,解析器将它们保存在不同的AST节点中,如此处所示, ClassDeclaration ClassExpression 在AST树结果中是不同的节点类型:



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



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




  • ClassBody

  • MethodDefinition <
  • ClassDeclaration

  • ClassExpression

  • MetaProperty



由于AST语法不是标准的,根据解析器的不同,可能有更多或更少的类型,但是重要的是注意到,当代码进入类声明或类表达式时,将以不同的方式呈现JavaScript引擎/ p>

这意味着,Class和Function声明不能交换。你可以看到这个,如果你试图写

  class notWorking {
return 1; //< - 创建一个解析器错误
};

这是因为当解析器遇到类关键字时,它将开始将以下代码视为ClassBody的ClassDeclaration或ClassExpression,然后它会显示出来找到MethodDefinitions。



这是一个小问题,因为创建私有变量有点更具挑战性。函数声明可以像这样定义一个私有变量:

  function myClass(){
var privateVar;
}

类声明不能这样:

  class myClass {
var privateVar; //错误:应该是一个方法
}

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



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



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



因此,将来您可能会说

  class myClass {
#privateVar; //这可能在未来有效吗?
}

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



JavaScript ES6类中的私有属性

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

自然地,类和函数之间有更多的区别。 其中一个是起吊 1 - 与函数不同,您不能在范围内声明任何位置:


函数声明和类$之间的一个重要区别b $ b声明是该函数声明被提升,并且类
声明不是。你首先需要声明你的类,然后
访问它


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

  function foo1(){} //可以在声明前使用
class foo2 {} // new foo2();仅在此声明之后才起作用

类表达式与功能演示非常相似,例如可以分配到一个变量:

  var myClass = class foobar {}; 

更多的区别是 1


  1. Class exression / declaration主体始终以严格模式执行 - 无需手动指定

  2. 类具有特殊关键字构造函数 - 只能有一个的,或者抛出错误。函数可以具有名为constructor的函数变量的多个定义。

  3. 类具有与父类构造函数相关的特殊关键字 super 。如果你在构造函数内部,你可以调用 super(x,y); 来调用父类构造函数,但是在Method中可以调用 super.foobar()来创建调用任何父类函数。这种功能不适用于标准功能,尽管您可以使用某些自定义黑客进行模拟。

  4. 在课堂内部,您可以使用 static 关键字定义功能,因此只能使用 ClassName.FunctionName() -syntax。

  5. 类声明和表达式都可以使用 extends 关键字,如 class Dog extends Animal

  6. MethodDeclaration不需要函数-prefix,因此您可以在类m中定义函数ok,如下所示: class m {ok(){}} 。实际上甚至不允许将函数定义为 class m {function ok(){}}

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



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



编辑:同样,ES6类语法另一个限制:它不允许成员函数使用脂肪箭头使用词法绑定。 ES7似乎有实验功能允许。这可以用于例如绑定方法到事件处理程序时,相关的问题是这里



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


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

This syntax:

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

is basically same as:

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?

解决方案

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 prosessing 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 resultin AST tree:

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

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

  • ClassBody
  • MethodDefinition
  • ClassDeclaration
  • ClassExpression
  • MetaProperty

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 intepreted 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
};

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 expexts 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;
}

The class declaration can not have this:

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

Thus, in the future you might be able to say

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

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

Private properties in JavaScript ES6 classes

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

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 exressions, for example they can be assigned to a variable:

var myClass = class foobar {};

More differences are 1

  1. The Class exression / 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.

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.

EDIT: 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/Classes

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

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