我为什么要使用ES6类?
我有很多关于ES6类的问题。
因为我知道如何使用函数和WebComponent,React&so。 我没有看到使用它的许多好处。
我想知道使用类有什么好处。 我读到public / private / static将成为ES7的一部分。 所以我目前没有看到使用它的意思。
而且,类会是面向对象的概念,还是“javascript对象概念”? 这是不是说我不能用.prototype
来修改它? 还是只是两个不同的方式来声明它是同一个对象。
速度有没有好处? 如果您拥有Big Java应用程序这样的大型应用程序,维护/理解起来会更容易一些吗?
tl;dr : The question is in the title.
信息 :我注意到现在人们还是来看这个2年多前的q / a了。 答案仍然是准确的,但记住JavaScript已经演变了一点。
无论你做什么,(几乎)完全取决于你。 新的东西大多只是语法糖。 (但是,你知道,好样的糖。)
而且,类会是面向对象的概念,还是“javascript对象概念”?
这与我们一直使用的原型inheritance是一样的,只是语法更简洁,更方便。 (特别是在从Array
或Error
派生的情况下,ES5和更早的版本无法做到这一点,现在可以使用Reflect.construct
[ spec , MDN ],但是当从它们派生时必须特别对待Array
和Error
没有class
, class
与其他 class
完全一样。)
这是不是说我不能用.prototype来修改它?
不,您可以在创build类之后,在类的构造函数中修改prototype
对象。 例如,这是完全合法的:
class Foo { constructor(name) { this.name = name; } test1() { console.log("test1: name = " + this.name); } } Foo.prototype.test2 = function() { console.log("test2: name = " + this.name); };
速度有没有好处?
通过为此提供一个特定的习惯用法,我想这可能是引擎可能能够做一个更好的工作优化。 但他们已经非常擅长优化,我不会指望有重大的不同。
我为什么要使用ES6类?
您可能select的理由:
-
语法比较简单,不易出错。
-
使用新的语法来设置inheritance层次比旧的要容易得多 (而且也不太容易出错)。
-
class
保护你从通用的错误,没有使用new
的构造函数(通过构造函数抛出一个exception,如果this
不是一个有效的对象的构造函数)。 -
调用父原型的一个方法的版本比旧的(
super.method()
而不是ParentConstructor.prototype.method.call(this)
或Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)
)。 -
你可以从
Array
派生(jQuery可能会做到这一点,如果它已经可能,当Resig启动它)和Error
。
以下是层次结构的语法比较:
// ES6 class Person { constructor(first, last) { this.first = first; this.last = last; } personMethod() { // ... } } class Employee extends Person { constructor(first, last, position) { super(first, last); this.position = position; } employeeMethod() { // ... } } class Manager extends Employee { constructor(first, last, position, department) { super(first, last, position); this.department = department; } personMethod() { const result = super.personMethod(); // ...use `result` for something... return result; } managerMethod() { // ... } }
与
// ES5 var Person = function(first, last) { if (!(this instanceof Person)) { throw new Error("Person is a constructor function, use new with it"); } this.first = first; this.last = last; }; Person.prototype.personMethod = function() { // ... }; var Employee = function(first, last, position) { if (!(this instanceof Employee)) { throw new Error("Employee is a constructor function, use new with it"); } Person.call(this, first, last); this.position = position; }; Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Employee; Employee.prototype.employeeMethod = function() { // ... }; var Manager = function(first, last, position, department) { if (!(this instanceof Manager)) { throw new Error("Manager is a constructor function, use new with it"); } Employee.call(this, first, last, position); this.department = department; }; Manager.prototype = Object.create(Employee.prototype); Manager.prototype.constructor = Manager; Manager.prototype.personMethod = function() { var result = Employee.prototype.personMethod.call(this); // ...use `result` for something... return result; }; Manager.prototype.managerMethod = function() { // ... };
正如你所看到的,那里有很多重复和冗长的东西,很容易出错和重新input无聊(这就是为什么我写了一个脚本来做到这一点 )。
ES6类是我们今天使用的原型类系统的语法糖。 他们使你的代码更加简洁和自我logging,这是足够的理由使用它们(在我看来)。
使用Babel来传输这个ES6类:
class Foo { constructor(bar) { this._bar = bar; } getBar() { return this._bar; } }
会给你类似的东西:
var Foo = (function () { function Foo(bar) { this._bar = bar; } Foo.prototype.getBar = function () { return this._bar; } return Foo; })();
第二个版本并不复杂,它是更多的代码来维护。 当涉及到inheritance时,这些模式变得更加复杂。
因为这些类可以编译成我们一直使用的原型模式,所以可以对它们进行相同的原型操作。 这包括在运行时添加方法等,访问Foo.prototype.getBar
等方法。
今天在ES6中有一些基本的隐私支持,虽然它是基于不导出你不想访问的对象。 例如,您可以:
const BAR_NAME = 'bar'; export default class Foo { static get name() { return BAR_NAME; } }
而BAR_NAME
将不可用于其他模块直接引用。
很多图书馆都试图支持或解决这个问题,比如Backbone和它的extends
助手,它采用了类似于方法的函数和属性的未经validation的散列,但是没有包含系统原型的inheritance,不涉及原型。
随着JS代码变得越来越复杂,代码库越来越大,我们开始发展大量模式来处理inheritance和模块等事情。 IIFE用于创build模块的私有范围有很多括号和parens; 丢失其中一个会导致一个有效的脚本完成不同的操作(在模块可以将下一个模块作为parameter passing给它时跳过分号)。
tl; dr:这是我们已经做的糖的事情,并且使你的意图在代码中清楚。