>  기사  >  웹 프론트엔드  >  es6 클래스 구문 설탕입니까?

es6 클래스 구문 설탕입니까?

青灯夜游
青灯夜游원래의
2022-10-17 18:03:101821검색

클래스는 구문 설탕입니다. 이유: 클래스는 프로토타입 상속 구현을 기반으로 하며 이는 언어 기능에 영향을 주지 않습니다. 문법 작성 및 읽기를 용이하게 할 뿐입니다. 클래스의 본질은 객체 프로토타입 작성을 더 명확하고 명확하게 만들 수 있는 기능입니다. 객체 지향 프로그래밍의 문법과 비슷합니다.

es6 클래스 구문 설탕입니까?

이 튜토리얼의 운영 환경: Windows 7 시스템, ECMAScript 버전 6, Dell G3 컴퓨터.

ES6 class class - 구문 설탕

class(class)는 객체의 템플릿으로 도입되었으며 클래스는 class 키워드를 통해 정의될 수 있습니다. 그 본질은 구문 설탕으로 간주될 수 있는 함수로, 객체 프로토타입의 작성 방법을 더 명확하고 객체 지향 프로그래밍의 구문과 더 유사하게 만듭니다.

클래스는 여전히 프로토타입 상속 구현을 기반으로 하며 언어 기능에 영향을 미치지 않습니다. 단지 쓰기와 읽기를 용이하게 할 뿐입니다

ES6 클래스라고 하는 이유는 무엇입니까? are syntactic sugar

다음을 질문과 함께 읽어봅시다.

  • ES6 클래스가 Syntactic Sugar라고 하는 이유는 무엇인가요?
  • 클래스는 프로토타입의 Syntactic Sugar인가요?
  • 그럼 프로토타입을 사용하여 Syntactic Sugar를 구현하는 방법은 무엇인가요? 수업?

1. 프로토타입 기반 OOP

먼저 프로토타입 예를 살펴보겠습니다.

function Person (name, sex) {
	this.name = name
	this.sex = sex
}
 
function Man (name) {
	this.name = name
}
 
Man.prototype = new Person('', 'male')
 
let Jy = new Man('Jy')
 
console.log(Jy.name, Jy.sex) // Jy, male

이것은 프로토타입을 사용하는 방법에 대한 매우 간단한 예입니다. 사람은 이름과 성별을 가지며 남자는 남자입니다. . 사람, Jy는 남자입니다. 먼저 이 예제를 기억하고 아래 클래스를 사용하여 이 예제를 다시 작성하겠습니다.

팁: Brendan Eich가 Java의 OOP에 더 가깝게 만들기 위해 new, this 등을 추가했습니다. 관심 있는 독자는 관련 정보를 직접 확인할 수 있습니다.

2. ES6 클래스의 OOP

class Person {
	constructor (name, sex) {
		this.name = name
		this.sex = sex
	}
}
 
class Man extends Person {
	constructor (name) {
		super('', 'male')
		this.name = name
	}
}
 
let Jy = new Man('Jy')
 
console.log(Jy.name, Jy.sex) // Jy, 'male'

이 예제를 다시 작성하여 클래스, 생성자, 확장 및 슈퍼라는 단어를 사용합니다.

3. 프로토타입(ES6 사양)을 사용하여 구현된 클래스 OOP

ES6 이전에는 JS 객체가 실제로 속성의 모음이었고 속성은 키-값 쌍(키, 값)의 집합이었습니다. 문자열이나 기호, 값에는 데이터 속성 특성값과 접근자 특성값이 포함됩니다.

평범한 속성도 괜찮다고 하셨는데, 객체 아래에 메소드도 있지 않나요? 어떻게 속성의 모음이 되었나요?

사실 ES5 사양에 등장하는 메소드의 정의는 "속성의 값인 함수"인데, 이는 객체의 함수 속성일 뿐 메소드라고 부를 수는 없습니다. ES6가 등장하기 전까지는 아니었습니다. 방법 정의가 사양에 포함되었습니다.

ES3의 OOP와 관련된 것들을 생각할 수 있습니다: 프로토타입, 신규, this, 생성자, 인스턴스 오브는 물론 표준 __proto__ 속성도 아닙니다.

다행히도 ES5에서는 이를 완성하고 완성하기 위해 많은 메소드를 추가했습니다:

  • Object.defineProperty
  • Object.freeze
  • Object.create
  • Object.getPrototypeOf
  • Object.setPrototypeOf
  • isPrototypeOf
  • ...

코드를 다시 살펴보겠습니다.

let obj = {
	name: 'Jy',
	speak () { // Note: it's not speak: function () {}
		console.log(this.name, super.name)
	}
}
 
obj.speak() // Jy, undefined
 
Object.setPrototypeOf(obj,  { name: 'super' })
 
obj.speak() // Jy, super
 
let speak = obj.speak
speak() // undefined, super

obj.speak는 ES6에서 메소드로 정의되며, [[homeObject]] 속성을 가지며, homeObject는 메소드가 호출되는 객체를 가리킵니다( code 가운데 손가락은 obj)이며, 이는 개체에 바인딩된 내부 슬롯입니다. 즉, 수정할 수 없으며 이는 하드코딩되는 것과 같습니다.

그럼 homeObject의 용도는 무엇인가요? super와 밀접한 관련이 있습니다. super 키워드를 구문 분석하면 homeObject의 프로토타입이 검색됩니다.

간단히 말하면 다음 두 가지 공식으로 요약할 수 있습니다.

  • let homeObj = Method[[HomeObject]] = obj
  • super = Object.getPrototypeOf(homeObj)

참고: homeObject는 정적으로 바인딩됩니다. 내부 슬롯에서는 슈퍼가 동적으로 검색됩니다.

super에 대해 이야기한 후, 확장 및 생성자에 대해 이야기해 보겠습니다.

class A extends B { }
 
class A extends B {
	constructor (...args) {
		super(args)
	}
}
 
class C extends null { }

extends는 주로 다음 두 가지 작업을 수행합니다.

  • Object.setPrototypeOf(A, B)
  • Object.setPrototypeOf(A.prototype, B.prototype )

부모 클래스가 null이면 Object.setPrototypeOf(C.prototype, null)을 실행합니다.

위 코드의 첫 번째 부분과 두 번째 부분의 차이점은 생성자가 명시적으로 선언되었는지 여부이므로 이 두 코드도 마찬가지입니다. 동등한? ? 대답은 동일합니다.

사양에서는 다음과 같이 정의합니다.

코드의 세 번째 부분은 null을 상속합니다. 구문 오류를 보고하지 않지만 새 C를 만들 수는 없습니다. 그 이유는 null의 생성자가 호출되기 때문입니다. 새로운 경우이지만 null은 생성자가 아닙니다.

여기서 ES6의 클래스 oop 및 사양 선언은 모두 프로토타입을 사용하여 작동하는데 클래스가 프로토타입의 구문 설탕이라고 말할 수 있습니까?

4. 바벨 컴파일 클래스

실제 프로젝트에서는 대부분 바벨을 사용하여 ES6 및 7 코드를 컴파일하므로 이 섹션에서는 다음 바벨 컴파일 코드를 분석하여 일부 오류 보고서와 프로토타입을 사용하여 OOP를 구현하는 주제를 더 잘 표현하기 위한 유형 감지를 위한 일부 관련 코드입니다.

컴파일 전:

class A extends B {}
 
console.log(new A)

컴파일 후:

"use strict";
 
function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
    return o.__proto__ || Object.getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}
 
function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
 
function _setPrototypeOf(o, p) {
  _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };
  return _setPrototypeOf(o, p);
}
 
var A =
  /*#__PURE__*/
  function (_B) {
    _inherits(A, _B);
 
    function A() {
 
      return _getPrototypeOf(A).apply(this, arguments);
    }
 
    return A;
  }(B);
 
console.log(new A());

我们重点看_inherits 方法,跟我们上述说的extends做的两件事是一样的:

  • Object.setPrototypeOf(subClass, superClass)
  • Object.setPrototypeOf(subClass.prototype, superClass.prototype)

只不过它采用的是Object.create方法,这两个方法的区别可以去MDN上查看。

再看function A内部,其实就是执行了B的构造器函数来达到super(arguments)的效果, 这个与规范:如果没有显示声明constructor会自动加上constructor是一致的。

5. 总结

至此,我们终于理解了为什么class是原型的语法糖以及如何使用原型来实现class这一语法糖。

但切记我们使用原型的目的并不是来模拟class oop的,prototype based的oop应该用prototype去理解而不是class。

ES6的class oop 是不完备的 ,例如abstract class 、interface、private等都还没有,不过有些功能已经在提案中了,大家可以拥抱它,或者TypeScript是个不错的选择,如果你的项目中使用到了TS, 欢迎你到评论区分享你的感受。

【相关推荐:javascript视频教程编程视频

위 내용은 es6 클래스 구문 설탕입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.