Background of Class
Javascript is an object-based language, and almost everything you encounter is an object. However, it is not a true OOP (Object-oriented JavaScript) language, and ES6 class writing just makes writing Object prototypes clearer and more like the syntax of object-oriented programming.
What problems does ES6 Class solve? We can start with two things, one is to solve the problem of code duplication, and the other is to solve the problem that instances need to be related, that is, based on the same prototype object.
1. Start with function encapsulation
First we encapsulate a generic function
function Cat(name, color) {
return {
name: name,
color: color,
};
}
let cat1 = Cat("Heavy hair"."Yellow");
let cat2 = Cat("二毛"."Black");
Copy the code
But cat1 and CAT2 are not intrinsically related to each other to reflect that they are instances of the same archetypal object.
To solve the problem of generating instances from prototype objects, Javascript provides a Constructor pattern.
A constructor is a normal function that uses the this variable inside. Using the new operator on the constructor generates the instance, and the this variable is bound to the instance object.
function Cat(name, color) {
this.name = name;
this.color = color;
}
let cat1 = new Cat("Heavy hair"."Yellow");
let cat2 = new Cat("二毛"."Black");
cat1.constructor === cat2.constructor; // T indicates that the instances all point to the same constructor
cat1 instanceof Cat; // T
cat2 instanceof Cat; // T
Copy the code
But for some common properties and methods on objects, we want to reuse them, that is, every instance points to that memory address.
JS specifies that each constructor has a prototype property that points to another object (the prototype object). All properties and methods of this object are inherited by instances of the constructor.
So we define some immutable properties and methods on our prototype objects,
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "Felines.";
Cat.prototype.eat = function () {
console.log("Eat a mouse.");
};
let cat1 = new Cat("Heavy hair"."Yellow");
let cat2 = new Cat("二毛"."Black");
cat1.eat === cat2.eat; // T This method points to the same memory address, which improves the running efficiency
Copy the code
2. A few ways to judge a prototype
Object.prototype.isPrototypeOf(obj)
Used to test whether one object obj exists on the prototype chain of another object.Object.prototype.hasOwnProperty()
Determine whether an attribute is local or inherits from the Prototype object- The in operator,
prop in object
To determine whether an instance contains a property (including on the stereotype chain)
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "Felines.";
Cat.prototype.eat = function () {
console.log("Eat a mouse.");
};
let cat1 = new Cat("Heavy hair"."Yellow");
Cat.prototype.isPrototypeOf(cat1); // T
cat1.hasOwnProperty("name"); // T
cat1.hasOwnProperty("type"); // F
"name" in cat1; // T
"type" in cat1; // T
Copy the code
Class grammar sugar
While this is a far cry from traditional object-oriented languages such as C++ and Java, ES6 offers a more traditional approach, introducing the concept of a Class as a template for objects. So ES6’s class can be thought of as just a syntactic sugar.
Let’s rewrite the above example using Class
class Cat {
constructor(name, color) {
this.name = name;
this.color = color;
}
eat() {
console.log("Eat a mouse.");
}
// You can write type as a getter method on the prototype
get type() {
return "Felines."; }}// The type attribute could also be defined this way, but it doesn't feel right, and maybe Class doesn't encourage us to define shared attributes directly on the prototype
// prototype. Type = "Cat ";
Cat.prototype; // {constructor,eat,type.. }
Copy the code
See the previous article for the basic usage of Class
Class compiler parsing
Babel compilation
Let’s look at what ES6 classes look like when compiled by Babel, for example ⬇️
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
static run() {
console.log("run");
}
say() {
console.log("hello!");
}
}
Person.run();
let p = new Person("Zhang".18);
Copy the code
Babel ⬇️
"use strict";
/** * define attribute *@param {*} target
* @param {array} props* /
function _defineProperties(target, props) {
for (let i = 0; i < props.length; i++) {
let descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor); }}/** * add attributes/methods to the constructor@param {*} Constructor *@param {array} ProtoProps Prototype properties - Add to prototype objects *@param {array} StaticProps Static property - added directly to the constructor itself *@returns* /
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
let Person = (function () {
function Person(name, age) {
// 1. Check whether the constructor is called via the new operator, if this is the Person instance, if not this is undefined,
if(! (this instanceof Person)) {
throw new TypeError("Cannot call a class as a function");
}
this.name = name;
this.age = age;
}
// 2. Add a property/method to the constructor, a stereotype property/method to the second argument, and a morphological property/method to the third argument
_createClass(
Person,
[
{
key: "say".value: function say() {
console.log("hello!"); },},], [{key: "run".value: function run() {
console.log("run!"); }},]);// 3. Return the new constructor
returnPerson; }) (); Person.prototype.say();// hello!
Person.run(); // run!
Copy the code
It can be seen that the main steps are as follows:
The constructor of a Class is essentially a constructor when compiled
- First, we determine how Class is called, requiring the use of new calls
- Then through
_createClass
Methods distinguish between prototypical methods and static methods - At last,
_defineProperties
Method to add attributes/methods
In the next article, we will continue to look at the “inheritance” mechanism of a Class
Reference: www.ruanyifeng.com/blog/2010/0…