小编典典

ES2015(ES6)`class`语法有什么好处?

javascript

我对ES6类有很多疑问。

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

而且,是class另一种OOP还是JavaScript的原型继承?我可以使用修改它.prototype吗?还是只是同一对象,而是两种不同的声明方法。

有速度好处吗?如果您拥有大型应用程序(例如大型应用程序),可能更容易维护/理解?


阅读 412

收藏
2020-05-01

共1个答案

小编典典

新的class语法是,对于现在,大多是语法sugar。(但是,您知道,这是很好的sugar。)ES2015-ES2019中class没有什么可以构造函数无法做到的,并且Reflect.construct(包括子类ErrorArray¹)也无法做到。(有

有可能在ES2021一些东西,你可以做class,你不能这样做,否则:私人领域私有方法静态字段/私有静态方法。)

而且,是class另一种OOP还是JavaScript的原型继承?

这与我们一直拥有的原型继承相同,只是如果您喜欢使用构造函数(newFoo等等),则使用更简洁,更方便的语法。(特别是在源自Array或的情况下Error,这是您在ES5和更早版本中无法实现的。您现在可以使用Reflect.construct[
specMDN],但不能使用旧的ES5样式。)

我可以使用修改它.prototype吗?

是的,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);
};

有速度好处吗?

通过提供这种特定的成语,我想这是可能的发动机也许能做得更好优化。但是他们已经非常擅长优化,我希望不会有太大的区别。

ES2015(ES6)class语法有什么好处?

简要地说:如果您一开始不使用构造函数,那么首选Object.create或类似的构造函数class对您没有用。

如果确实使用构造函数,则有一些好处class

  • 语法更简单,更不易出错。

  • 这是 很多 容易(再次,不易出错)使用新的语法比旧的设置继承层次。

  • class保护您免受无法new与构造函数一起使用的常见错误(如果this不是有效的构造函数,则使构造函数抛出异常)。

  • 使用新语法调用父原型方法的版本比使用旧语法(super.method()而不是ParentConstructor.prototype.method.call(this)or Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this))要简单得多。

这是层次结构的语法比较:

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

例:

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

// **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;

}
2020-05-01