Maison >interface Web >Questions et réponses frontales >La classe es6 est-elle du sucre syntaxique ?

La classe es6 est-elle du sucre syntaxique ?

青灯夜游
青灯夜游original
2022-10-17 18:03:101917parcourir

la classe est du sucre syntaxique. Raison : la classe est basée sur la mise en œuvre de l'héritage des prototypes, qui n'a aucun impact sur le fonctionnement du langage. Elle facilite simplement l'écriture et la lecture de la grammaire. L'essence de la classe est la fonction, ce qui peut rendre l'écriture des prototypes d'objets plus claire et plus claire. plus comme la grammaire de la programmation orientée objet.

La classe es6 est-elle du sucre syntaxique ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.

Classe ES6 - sucre syntaxique

class (class) est introduit comme modèle pour les objets, et les classes peuvent être définies via le mot-clé class. Son essence est une fonction, qui peut être considérée comme un sucre syntaxique, rendant la méthode d'écriture du prototype d'objet plus claire et plus proche de la syntaxe de la programmation orientée objet.

Sa classe est différente des autres langages. Elle est toujours basée sur la mise en œuvre de l'héritage prototypique, qui n'a aucun impact sur le fonctionnement du langage. Elle facilite simplement votre écriture et votre lecture

Pourquoi dit-on que les classes ES6. sont du sucre syntaxique

Lisons ce qui suit avec des questions :

  • Pourquoi dit-on que la classe ES6 est du sucre syntaxique
  • La classe est-elle le sucre syntaxique du prototype ?
  • Alors comment utiliser le prototype pour réaliser le sucre syntaxique ? de classe ?

1. POO basée sur un prototype

Regardons d'abord un exemple de prototype :

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

C'est un exemple très simple de la façon dont nous utilisons les prototypes. La personne a un nom et un sexe, et l'homme est un homme. .Personne, Jy est un homme. Rappelons-nous d'abord cet exemple, et nous réécrirons cet exemple en utilisant la classe ci-dessous.

Conseils : nouveau, ceci, etc. ont été ajoutés par Brendan Eich pour le rendre plus proche de la POO de Java. Les lecteurs intéressés peuvent vérifier les informations pertinentes par eux-mêmes.

2. POO de la classe ES6

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'

En réécrivant cet exemple, nous utilisons les mots classe, constructeur, extends et super. Parlons ensuite de ce qui est fait avec eux dans la spécification ES6.

3. Classe POO implémentée à l'aide de Prototype (spécification ES6)

Avant ES6, les objets JS étaient en fait des collections d'attributs, et les attributs étaient un ensemble de paires clé-valeur (clé, valeur). Chaîne ou symbole, la valeur inclut la valeur caractéristique de l'attribut de données et la valeur caractéristique de l'accesseur.

Vous avez dit que les attributs ordinaires sont bien, mais n'y a-t-il pas des méthodes sous les objets ? Comment est-il devenu une collection d’attributs ?

En fait, la définition de méthode qui apparaît dans la spécification ES5 est "une fonction qui est la valeur d'une propriété", qui n'est qu'un attribut de fonction de l'objet et ne peut pas être appelée une méthode. Ce n'est que lorsque ES6 est apparu que. Les définitions de méthode ont été incluses dans la spécification.

Nous pouvons penser à des choses liées à la POO dans ES3 : prototype, nouveau, this, constructeur, instanceof, pas même la propriété __proto__ standard.

Heureusement, dans ES5, nous avons ajouté de nombreuses méthodes pour le compléter et le rendre complet :

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

Regardons à nouveau un morceau de code :

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 est défini dans ES6 comme Method. Il a l'attribut [[homeObject]], et homeObject pointe vers l'objet sur lequel la méthode est appelée. (code Le majeur est obj), qui sont des Slots internes liés à l'objet, c'est-à-dire que vous ne pouvez pas le modifier, ce qui équivaut à être codé en dur.

Alors à quoi sert homeObject ? Il est étroitement lié à super. Lorsque le mot-clé super est analysé, le prototype de homeObject sera trouvé.

En termes simples, cela peut être résumé par les deux formules suivantes :

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

Remarque : homeObject est lié statiquement à interne dans les emplacements, tandis que super est recherché dynamiquement.

Après avoir parlé de super, parlons des extensions et du constructeur

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

extends fait principalement les deux choses suivantes :

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

Si la classe parent est nulle, exécutez Object.setPrototypeOf(C.prototype, null)

La différence entre la première et la deuxième partie du code ci-dessus est de savoir si le constructeur est explicitement déclaré, ces deux morceaux de code le sont aussi équivalent? ? La réponse est équivalente.

Voici comment cela est défini dans la spécification :

La troisième partie du code hérite de null. Elle ne signalera pas d'erreur de syntaxe, mais nous ne pouvons pas créer un nouveau C. La raison est que le constructeur de null sera appelé. quand il est nouveau, mais pas le constructeur null.

Voir ici, les déclarations de classe oop et de spécification d'ES6 utilisent toutes des prototypes pour fonctionner, alors pouvons-nous dire que la classe est le sucre syntaxique des prototypes ?

4. Classe compilée par Babel

Dans les projets réels, nous utilisons principalement Babel pour compiler les codes ES6 et 7, donc dans cette section, nous analyserons le code compilé par Babel suivant, qui omettra certains rapports d'erreurs et Du code connexe pour la détection de type afin de mieux présenter le sujet de l'utilisation de prototypes pour implémenter la POO.

Avant la compilation :

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

Après la 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视频教程编程视频

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn