ES2015(ES6)`class`语法有什么好处? [英] What benefits does ES2015 (ES6) `class` syntax provide?

查看:52
本文介绍了ES2015(ES6)`class`语法有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对ES6类有很多疑问.

使用class语法有什么好处?我读到public/private/static将成为ES7的一部分,这是一个原因吗?

此外,class是另一种OOP还是JavaScript的原型继承?我可以使用.prototype对其进行修改吗?还是它只是同一个对象,但是用两种不同的方式声明它.

有速度优势吗?如果您拥有像大型应用程序这样的大型应用程序,也许维护/理解起来会更容易?

解决方案

对于 now 而言,新的class语法主要是语法糖. (但是,您知道,是一种糖.)在ES2015-ES2019中,没有任何class可以做的事,而构造函数和Reflect.construct都做不到(包括对Array¹). ( 可能在ES2021中可以通过class进行其他操作,否则无法进行其他操作:私有方法静态字段/私有静态方法.)

此外,class是另一种OOP还是JavaScript的原型继承?

这是我们一直拥有的原型继承,只是使用更简洁,更方便的语法 if (如果您喜欢使用构造函数)(new Foo等). (特别是在从ArrayError派生的情况下,您在ES5和更早版本中无法做到这一点.您现在可以使用Reflect.construct [

vs.

// **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() {
    // ...
};

实时示例:

 // **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() {
    return "Result from personMethod: this.first = " + this.first + ", this.last = " + this.last;
};

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.personMethod = function() {
    var result = Person.prototype.personMethod.call(this);
    return result + ", this.position = " + this.position;
};
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);
    return result + ", this.department = " + this.department;
};
Manager.prototype.managerMethod = function() {
    // ...
};        

var m = new Manager("Joe", "Bloggs", "Special Projects Manager", "Covert Ops");
console.log(m.personMethod()); 

如您所见,那里有很多重复且冗长的内容,很容易出错,而且很无聊(这就是我写执行此操作的脚本,回到过去).


¹在ES2015-ES2018中,class无法完成构造函数和Reflect.construct(包括子类化ErrorArray)无法做到的事情"

示例:

 // Creating an Error subclass:
function MyError(...args) {
  return Reflect.construct(Error, args, this.constructor);
}
MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;
MyError.prototype.myMethod = function() {
  console.log(this.message);
};

// Example use:
function outer() {
  function inner() {
    const e = new MyError("foo");
    console.log("Callng e.myMethod():");
    e.myMethod();
    console.log(`e instanceof MyError? ${e instanceof MyError}`);
    console.log(`e instanceof Error? ${e instanceof Error}`);
    throw e;
  }
  inner();
}
outer(); 

 .as-console-wrapper {
  max-height: 100% !important;
} 

I have many question about ES6 classes.

What's the benefit of using class syntax? I read that public/private/static will be part of ES7, is that a reason?

Moreover, is class a different kind of OOP or it still JavaScript's prototypical inheritance? Can I modify it using .prototype ? Or is it just the same object but two different ways to declare it.

Are there speed benefits? Maybe it's easier to maintain/understand if you have a big application like big app?

解决方案

The new class syntax is, for now, mostly syntactic sugar. (But, you know, the good kind of sugar.) There's nothing in ES2015-ES2019 that class can do that you can't do with constructor functions and Reflect.construct (including subclassing Error and Array¹). (There is likely to be some things in ES2021 that you can do with class that you can't do otherwise: private fields, private methods, and static fields/private static methods.)

Moreover, is class a different kind of OOP or it still JavaScript's prototypical inheritance?

It's the same prototypical inheritance we've always had, just with cleaner and more convenient syntax if you like using constructor functions (new Foo, etc.). (Particularly in the case of deriving from Array or Error, which you couldn't do in ES5 and earlier. You can now with Reflect.construct [spec, MDN], but not with the old ES5-style.)

Can I modify it using .prototype?

Yes, you can still modify the prototype object on the class's constructor once you've created the class. E.g., this is perfectly legal:

class Foo {
    constructor(name) {
        this.name = name;
    }

    test1() {
        console.log("test1: name = " + this.name);
    }
}
Foo.prototype.test2 = function() {
    console.log("test2: name = " + this.name);
};

Are there speed benefits?

By providing a specific idiom for this, I suppose it's possible that the engine may be able to do a better job optimizing. But they're awfully good at optimizing already, I wouldn't expect a significant difference.

What benefits does ES2015 (ES6) class syntax provide?

Briefly: If you don't use constructor functions in the first place, preferring Object.create or similar, class isn't useful to you.

If you do use constructor functions, there are some benefits to class:

  • The syntax is simpler and less error-prone.

  • It's much easier (and again, less error-prone) to set up inheritance hierarchies using the new syntax than with the old.

  • class defends you from the common error of failing to use new with the constructor function (by having the constructor throw an exception if this isn't a valid object for the constructor).

  • Calling the parent prototype's version of a method is much simpler with the new syntax than the old (super.method() instead of ParentConstructor.prototype.method.call(this) or Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)).

Here's a syntax comparison for a hierarchy:

// ***ES2015+**
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() {
        // ...
    }
}

Example:

// ***ES2015+**
class Person {
    constructor(first, last) {
        this.first = first;
        this.last = last;
    }

    personMethod() {
        return `Result from personMethod: this.first = ${this.first}, this.last = ${this.last}`;
    }
}

class Employee extends Person {
    constructor(first, last, position) {
        super(first, last);
        this.position = position;
    }

    personMethod() {
        const result = super.personMethod();
        return result + `, this.position = ${this.position}`;
    }

    employeeMethod() {
        // ...
    }
}

class Manager extends Employee {
    constructor(first, last, position, department) {
        super(first, last, position);
        this.department = department;
    }

    personMethod() {
        const result = super.personMethod();
        return result + `, this.department = ${this.department}`;
    }

    managerMethod() {
        // ...
    }
}

const m = new Manager("Joe", "Bloggs", "Special Projects Manager", "Covert Ops");
console.log(m.personMethod());

vs.

// **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() {
    // ...
};

Live Example:

// **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() {
    return "Result from personMethod: this.first = " + this.first + ", this.last = " + this.last;
};

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.personMethod = function() {
    var result = Person.prototype.personMethod.call(this);
    return result + ", this.position = " + this.position;
};
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);
    return result + ", this.department = " + this.department;
};
Manager.prototype.managerMethod = function() {
    // ...
};        

var m = new Manager("Joe", "Bloggs", "Special Projects Manager", "Covert Ops");
console.log(m.personMethod());

As you can see, lots of repeated and verbose stuff there which is easy to get wrong and boring to retype (which is why I wrote a script to do it, back in the day).


¹ "There's nothing in ES2015-ES2018 that class can do that you can't do with constructor functions and Reflect.construct (including subclassing Error and Array)"

Example:

// Creating an Error subclass:
function MyError(...args) {
  return Reflect.construct(Error, args, this.constructor);
}
MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;
MyError.prototype.myMethod = function() {
  console.log(this.message);
};

// Example use:
function outer() {
  function inner() {
    const e = new MyError("foo");
    console.log("Callng e.myMethod():");
    e.myMethod();
    console.log(`e instanceof MyError? ${e instanceof MyError}`);
    console.log(`e instanceof Error? ${e instanceof Error}`);
    throw e;
  }
  inner();
}
outer();

.as-console-wrapper {
  max-height: 100% !important;
}

这篇关于ES2015(ES6)`class`语法有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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