Home  >  Article  >  Web Front-end  >  Is es6 class syntactic sugar?

Is es6 class syntactic sugar?

青灯夜游
青灯夜游Original
2022-10-17 18:03:101868browse

class is syntactic sugar. Reason: class is based on the implementation of prototype inheritance, which has no impact on the function of the language. It just facilitates the writing and reading of grammar; the essence of class is function, which can make the writing of object prototypes clearer and more like the grammar of object-oriented programming. .

Is es6 class syntactic sugar?

The operating environment of this tutorial: Windows 7 system, ECMAScript version 6, Dell G3 computer.

ES6 class class - syntactic sugar

class (class) is introduced as a template for objects, and classes can be defined through the class keyword. Its essence is a function, which can be regarded as syntactic sugar, making the writing method of object prototype clearer and more like the syntax of object-oriented programming.

Its class is different from other languages. It is still based on the implementation of prototypal inheritance. It has no impact on the functions of the language. It just makes it easier for you to write and read.

Why is it said that ES6 classes are syntactic sugar?

Let’s read the following with questions:

  • Why is it said that ES6 classes are syntactic sugar?
  • Is class the syntactic sugar of prototype?
  • So how do you use prototypes to implement the syntactic sugar of class?

1. OOP based on Prototype

Let’s first look at a prototype example:

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

This is We use a very simple example of a prototype. Person has a name and gender, Man is a Person with a male gender, and Jy is a Man. Let's remember this example first, and we will rewrite this example using class below.

Tips: new, this, etc. were added by Brendan Eich to make it more like Java's OOP. Interested readers can check the relevant information by themselves.

2. OOP of ES6 Class

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'

We rewrite this example and use class, constructor, extends, super For these words, let’s talk specifically about what is done to them in the ES6 specification.

3. Class OOP implemented using Prototype (ES6 specification)

Before ES6, JS objects were actually collections of attributes, and attributes It is a set of key-value pairs (key, value). Key can be String or Symbol. Value includes data attribute characteristic values ​​and accessor characteristic values.

You said that ordinary attributes are fine, but aren’t there methods under objects? How did it become a collection of attributes?

In fact, the definition of method that appears in the ES5 specification is "function that is the value of a property", which is just a function attribute of the object. It cannot be called a method. It was not until ES6 appeared that Method was included in the specification. Definitions.

We can think of things related to OOP in ES3: prototype, new, this, constructor, instanceof, not even the standard __proto__ attributes.

Fortunately, in ES5 we have added many methods to complete it and make it complete:

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

Let’s look at a piece of code again:

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 is defined as Method in ES6. It has the attribute [[homeObject]], and homeObject points to the object on which the method is called (referring to obj in the code). It is Internal Slots bound to the object, that is, you cannot modify it, which is equivalent to being hardcoded.

So what is the use of homeObject? It is closely related to super. When the super keyword is parsed, the prototype of homeObject will be found.

To put it simply, it can be summarized as the following two formulas:

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

#Note: homeObject is statically bound in internal slots, while super is dynamically searched.

After talking about super, let’s talk about extends and constructor

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

extends mainly does the following two things:

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

If the parent class is null, execute Object.setPrototypeOf(C.prototype, null)

The difference between the first and second parts of the above code is whether the constructor is explicitly declared. So are these two pieces of code equivalent? The answer is equivalent.

This is how it is defined in the specification:

The third part of the code inherits null. It will not report a syntax error, but we cannot create a new C because it will Call the constructor of null, but null has no constructor.

Seeing this, ES6’s class oop and specification declarations all use prototypes to operate, so can we say that class is the syntax sugar of prototypes?

4. Class compiled by babel

In our actual projects, babel is often used to compile ES6 and 7 code, so in this section we Let’s analyze the following babel compiled code, which will omit some error reporting and type detection related codes to better present the theme of using prototypes to implement OOP.

Before compilation:

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

After compilation:

"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视频教程编程视频

The above is the detailed content of Is es6 class syntactic sugar?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn