Let’s start with a 50 cent background
Es6 is now widely available, thanks to Babel. JavaScript classes are essentially syntactic sugar for JavaScript’s existing prototype-based inheritance. Class syntax does not introduce a new object-oriented inheritance model to JavaScript. In other words, Babel implements classes and implements inheritance, which is essentially based on archetypes and chains of archetypes, so I’m going to go along with that, step by step, until I uncover how Babel implements classes and class inheritance.
Prototype and prototype chain
The concept of a prototype in javascript is a bit abstract and not easy to understand, so let’s just stick to the code and use the code to illustrate.
function Person (name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
let p1 = new Person('Joe', 18.'Front Siege Lion')
Copy the code
We create a constructor for Person and use new to create an instance of that object, object P1.
- In JS, every function has a prototype attribute.
- Every JS object (except null) has a __proto__ attribute. What does the Person prototype attribute point to? Is it the archetype of Person? Enter the following code in Chrome
We find that Person.prototype points to an object, which is actually p1’s prototype. As shown in figure:Therefore, we can also use the graph below to represent their relationship
- We said earlier that Person.prototype points to an object, so what’s in that object? Enter the following code in Chrome:
We find that Person.prototype is indeed an object with two attributes :constrcutor and __proto__. Constructor points to Person(), which means that js objects really do have a __proto__ attribute. What’s the relation between constructor and Person? In effect, the constructor property points to the constructor itself. There is a picture and there is a truth
- Each stereotype has a constructor property pointing to the associated constructor. Their relationship is as follows:
Person. Prototype has a __proto__ attribute. What is the __proto__ attribute? In other words, what is the archetype of the archetype. Let’s start with a picture
We find that it has only the constructor property, which points to Object() and no __proto__ property. Isn’t that interesting? So let’s do another experiment. As shown in figure
- Prototype objects are generated through the Object constructor. The __proto__ of the instance points to the prototype constructor, and the __proto__ of the Object constructor points to null
- Let’s sum it up with a picture:
This is actually the prototype chain.
Inheritance in ES5
Earlier we talked about archetypes and prototype chains, which is really just to set the stage for our talk about inheritance. Without further ado, let’s go to the code:
// We define an animal class with a type attribute in itfunction Animal (type) {
this.type = type} // All animals have ways to eatfunction () {
console.log('I'm eating.'} // Let's have a kittenfunction Cat() {} // Now we want to implement Cat to inherit Animal properties and methods.Copy the code
- The first way
Cat. Prototype = new Animal()let cat = new Cat()
console.log(cat.eat())
Copy the code
The result is shown in figure
function Animal (type) {
this.type = type
}
Animal.prototype.eat = function () {
console.log('I'm eating.')}function Cat (type) {
Animal.call(this, type)
}
Cat.prototype = new Animal()
let cat = new Cat('meow microphones')
console.log(cat.eat())
console.log(cat.type)
Copy the code
The running results are as follows:
function Animal (type, val) {
this.type = typeThis. sum = [4,5,6] this.setSum =function () {
this.sum.push(val)
}
}
Animal.prototype.eat = function () {
console.log('I'm eating.')}function Cat (type, val) {
Animal.call(this, type, val)
}
Cat.prototype = new Animal()
let cat = new Cat('meow microphones'1),let cat2 = new Cat('the cat 2', 2)
console.log(cat.setSum())
console.log(cat2.setSum())
console.log(cat.sum)
console.log(cat2.sum)
Copy the code
The running results are shown as follows:
- Method 2: This is when we have to bring out our ultimate artifact. It is ES5’s object.create () method. The code is as follows:
functionInherit (C, P) {// equal to the temporary constructor c. protoType = object.create (p.prototype); C.prototype.constructor = C; // constructor c.sup = P; // Store superclass}function Animal(type) {
this.type = type;
}
Animal.prototype.eat = function () {
console.log('All animals need to eat.')}function Cat(type, talk) {
Cat.super.call(this, type)
this.talk = talk
this.getTalk = function () {
return this.talk
}
}
inherit(Cat, Animal)
let cat = new Cat('cat'.'Let's meow.')
console.log(cat.getTalk())
Copy the code
The code runs as follows:
Babel’s implementation of es6 classes
In the background we’ve talked about how class inheritance in ES6 is really a syntactic sugar, and now we’re going to try to crack that sugar.
- The ES6 class overrides the above code
class Animal {
constructor (type) {
this.type = type
}
eat () {
console.log('All animals eat')
}
}
class Cat extends Animal {
constructor (type,talk) {
super(type// Constructor inherits the constructor attribute this.talk = talk}getTalk () {
return this.talk
}
}
let cat = new Cat('meow microphones'.Meow, meow, meow.) console.log(cat.getTalk()) // meow meow console.log(cat.type) // Meow meowCopy the code
- Implementation of classes in Babel
The implementation of classes in Babel consists of three main steps:- Step 1: constructor implementation, this part of the implementation is different from our normal constructor, wrapped in a self-executing function, code as follows
var Animal = function () { function Animal (type) { this.type = type this.getType = function () { return this.type } } return Animal }() var Cat = function () { function Cat (talk) { this.talk = talk this.getTalk = function () { return this.talk } } return Cat }() Copy the code
- Step 2: The following code:
function Animal() { return { name: 'cool', age: 18 } } let animal = new Animal() console.log(animal) // { name: 'cool', age: 18} Copy the code
So Babel checks this, and that’s what step two is going to do. The code is as follows:
var _classCallCheck = function (instance, Constructor) { if(! (instance instanceof Constructor)) { throw new TypeError("Cannot return an object."Var Animal = var Animal =function () { function Animal (type) { _classCallCheck(this, Animal) this.type = type}} ()... Cats are omitted hereCopy the code
- Step 3: Add methods to the prototype. The first two steps are mainly to implement and verify the constructor, and the third step is to add the method on the prototype to the corresponding class. How does Babel handle es6 class methods
class Animal { eat () { console.log('aaa')}sleep () { console.log('bbb')}}Copy the code
As in the above code, the eat and sleep methods are handled. So how do you add methods to an object? That’s right, the object.defineProperty () method is used to do this, and it’s also used in Babel. Back to our topic, in Babel, it is handled by the _createClass function. Without further ado, let’s go to the code:
/* _createClass() this function takes two arguments, one of which is the constructor of the class to add a method to. The second argument is an array object like this [{key:'eat', val: function eat () { console.log('aaa')}}] Did you suddenly see the light? So let's implement it */function definePropties (target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } var _createClass = function () { return function(Constructor, protoProps, staticProps) {// Add methods on the prototypeif(protoProps) definePropties(Constructor. Prototype, protoProps) // Add static methodsif (staticProps) definePropties(Constructor, staticProps) return Constructor } }() _createClass(Animal,[{ key: 'eat', value: function () { console.log('aaa')}}])Copy the code
At this point the Babel implementation class is basically implemented. The above code can see more, more thinking, or quite profit.
- Step 1: constructor implementation, this part of the implementation is different from our normal constructor, wrapped in a self-executing function, code as follows
An inherited implementation in Babel
In this section, we’ll talk about how Babel handles inheritance in ES6.
- The inherited implementation of Babel is basically the same as the inherited implementation of ES5 we talked about earlier. Let’s talk about it.
function _inherits(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true; }})if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
Copy the code
Ok, that’s all for this topic. Welcome to clap bricks.