Programing

ES2015 (ES6)`class` 구문은 어떤 이점을 제공합니까?

lottogame 2020. 10. 8. 07:36
반응형

ES2015 (ES6)`class` 구문은 어떤 이점을 제공합니까?


ES6 수업에 대해 많은 질문이 있습니다.

class구문 사용의 이점은 무엇입니까 ? 공개 / 비공개 / 정적이 ES7의 일부가 될 것이라고 읽었습니다. 그게 이유인가요?

또한 class다른 종류의 OOP입니까 아니면 여전히 JavaScript의 프로토 타입 상속입니까? 을 사용하여 수정할 수 있습니까 .prototype? 또는 동일한 객체이지만 선언하는 두 가지 방법입니다.

속도 이점이 있습니까? 큰 앱과 같은 큰 애플리케이션이 있다면 유지 관리 / 이해가 더 쉬울까요?


class구문 을 사용하는지 여부는 (거의) 전적으로 귀하에게 달려 있습니다 . 대부분은 구문 론적 설탕입니다. (하지만 좋은 종류의 설탕이 있습니다.) ES2015-ES2018 class에는 생성자 함수 Reflect.construct(서브 클래 싱 ErrorArray¹ 포함)로 할 수없는 작업이 없습니다 . (이 있습니다 당신이 할 수있는 ES2019 또는 ES2020에 뭔가 될 가능성이 class당신이 그렇지 않으면 할 수없는 : private 필드개인 방법 .)

또한 class다른 종류의 OOP입니까 아니면 여전히 JavaScript의 프로토 타입 상속입니까?

생성자 함수 ( 등)를 사용 하는 것을 좋아 한다면 더 깔끔하고 편리한 구문으로 우리가 항상 가지고 있었던 것과 동일한 프로토 타입 상속 new Foo입니다. (특히 ES5 및 이전 버전에서는 할 수 없었던 Arrayor Error에서 파생 된 경우 . 이제 Reflect.construct[ spec , MDN ]으로는 가능하지만 이전 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.

  • 구문이 더 간단하고 오류가 덜 발생합니다.

  • 그건 훨씬 더 쉽게 (다시, 더 적은 오류가 발생하기 쉬운) 이전보다 새로운 구문을 사용하여 상속 계층 구조를 설정합니다.

  • classnew생성자 함수와 함께 사용하지 못하는 일반적인 오류로부터 사용자를 보호합니다 (생성자에 this대해 유효한 객체가 아닌 경우 생성자가 예외를 throw하도록 함 ).

  • 새 구문을 사용하면 부모 프로토 타입 버전의 메서드를 호출하는 것이 이전 ( 또는 super.method()대신) 보다 훨씬 간단합니다 .ParentConstructor.prototype.method.call(this)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;
}


ES6 classes are syntactic sugar for the prototypical class system we use today. They make your code more concise and self-documenting, which is reason enough to use them (in my opinion).

Using Babel to transpile this ES6 class:

class Foo {
  constructor(bar) {
    this._bar = bar;
  }

  getBar() {
    return this._bar;
  }
}

will give you something like:

var Foo = (function () {
  function Foo(bar) {    
    this._bar = bar;
  }

  Foo.prototype.getBar = function () {
    return this._bar;
  }

  return Foo;
})();

The second version isn't much more complicated, it is more code to maintain. When you get inheritance involved, those patterns become even more complicated.

Because the classes compile down to the same prototypical patterns we've been using, you can do the same prototype manipulation on them. That includes adding methods and the like at runtime, accessing methods on Foo.prototype.getBar, etc.

There is some basic support for privacy in ES6 today, although it's based on not exporting the objects you don't want accessible. For example, you can:

const BAR_NAME = 'bar';

export default class Foo {
  static get name() {
    return BAR_NAME;
  }
}

and BAR_NAME will not be available for other modules to reference directly.

A lot of libraries have tried to support or solve this, like Backbone with their extends helper that takes an unvalidated hash of method-like functions and properties, but there's no consist system for exposing prototypical inheritance that doesn't involve mucking around with the prototype.

As JS code becomes more complicated and codebases larger, we've started to evolve a lot of patterns to handle things like inheritance and modules. The IIFE used to create a private scope for modules has a lot of braces and parens; missing one of those can result in a valid script that does something entirely different (skipping the semicolon after a module can pass the next module to it as a parameter, which is rarely good).

tl;dr: it's sugar for what we already do and makes your intent clear in code.

참고URL : https://stackoverflow.com/questions/30783217/what-benefits-does-es2015-es6-class-syntax-provide

반응형