preface
The traditional object-oriented language is through the class to define a class, but before ES6, JS does not have the class keyword, so it is how to achieve object-oriented? With these questions, let’s take a look at the tortuous path of JS object oriented.
The constructor
Javascript functions are divided into ordinary functions and arrow functions, and ordinary functions can be used as constructors in addition to performing their functions.
function Person(){}
Copy the code
Here we define a function that we execute using the new keyword, as follows
const wife = new Person();
console.log(wife)
Copy the code
Now that we have a wife object, which is an instance of Person, let’s print our new wife as follows:
At this point, the Wife object only has a translucent (non-enumerable) __proto__ property, so what if I wanted to set the age, name, and size of the wife object when I created it?
It’s actually quite simple, because it’s a constructor itself, so we just pass in the property we want to set as an argument, as shown here
function Person(age,name,sanwei){ this.age = age; this.name = name; this.sanwei = sanwei; } let wife = new Person(16,' like ','30,150,180');Copy the code
At this point our wife object contains name, age, and sanwei
The “this” in photoshop is divided into two cases
- If our constructor does not return a value or the return value is not an object, then
this
Point to our instantiated object. - If our constructor returns an object, then
this
Point to what we returned and find an object.
The first is the most common, because normally we don’t define a return value for the constructor.
prototype
Above we defined some attributes for Person, but what if we wanted to define methods? For example, if we want to define a KISS method, what should we do? It doesn’t make sense to define it directly in the constructor, because we’re redefining it every time we new it. Given this clarity, JS gives a prototype property for normal functions, so we just need to define the method on the function’s Prototype property. So we could end up writing it like this
Person.prototype.kiss = function() {
console.log('kiss' + this.name);
};
let wife = new Person(16.'like'.'30150180');
let wife2 = new Person(20.'sister'.'30180200');
wife.kiss();
wife2.kiss();
console.log(wife);
console.log(wife2);
Copy the code
__proto__
We didn’t find a defined kiss method for printing big wife and small wife. In this case, you just need to open the __proto__ property and look like this:
This is the kiss method we defined.
Through the above experiment, we found that when we access properties and methods on an object, if the object itself does not have the kiss method, it will look up __proto__. For example, in our example, the wife object itself does not have the KISS method, so it will look up __proto__. Finally, the kiss method is found. If __proto__ is not already on it, it will continue to look up the __proto__ property until it finds or __proto__ is null, which is the prototype chain.
If you’re careful, you’ll notice that Person. Prototype has a constructor attribute. Let’s talk about it.
constructor
From the above print, we can see that constructor points to a constructor (Person).
As we can see, the final output is true.
summary
From the above explanation, I think most of the students have a deep understanding of prototype, __proto__,constructor, I would like to summarize a picture, as follows
- Ordinary functions can be used as constructors
new
The keyword instantiates the object, such as let wife = new Person - The constructor Person has one itself
prototype
Reference, you can define class methods on it, and there’s aconstructor
The reference points to the constructorPerson
Itself, that is, the Person. The prototype. The constructor = = = the Person - The instance object has a __proto__ attribute that points to its constructor
prototype
“Wife.__proto__
===Person.prototype
inheritance
When it comes to object-oriented inheritance, we all know that Java implements inheritance using the extends keyword, but JS does not have extends (ES5). Let’s think about the nature of inheritance, which is that as long as the son inherits the father, then the father has all the sons.
Let’s look at the following example.
// Parent constructor
function Parent(name, age, identity) {
this.name = name;
this.age = age;
this.identity = identity;
}
Parent.prototype.say = function () {
console.log('identity' + this.identity)
}
// subconstructor
function Child(name, age, identity) {
this.name = name;
this.age = age;
this.identity = identity;
}
Child.prototype.say = function () {
console.log('identity' + this.identity)
}
Child.prototype.spendMoney = function () {
console.log('I'll buy buy buy buy')}Copy the code
The example defines two constructors, and it is clear that all attributes and methods in the child constructor can be derived from the parent constructor, except for the spendMoney method. As an aside, if I have 1yi, then my son really does not need to earn that 1yi, the truth is this truth, but in js code we should how to achieve it?
In the first step, we first eliminate the existing parent constructor on the childattribute
andmethods
After all, we have a family business to inherit. What the family doesn’t have, let’s reproduce.
// subconstructor
function Child(name, age, identity) {
}
Child.prototype.spendMoney = function () {
console.log('I'll buy buy buy buy')}Copy the code
Step 2: How about inheriting the attributes of the parent constructor first
Note that the parent constructor uses this. XXX = “(this.name = name) to add attribute values. We just need to change this to an instance of the subclass
So we could write it like this
// subconstructor
function Child(name, age, identity) {
this.Parent = Parent;
this.Parent(name,age,identity)
delete this.Parent;
}
let child1 = new Child('longhang'.12.'son')
Copy the code
Let’s print child1. It looks like this
Perfect. Clear your head
Parent = parent; parent = this.parent = parent;
2 The child class calls the constructor through this.Parent, so that this in Parent refers to an instance of the child class; 3 Remove the pointer this.Parent.
In fact, there is a more elegant way to use call or apply. The reason why we use the above way is to let our friends know the principle of call or apply.
// subconstructor
function Child(name, age, identity) {
Parent.call(this,name,age,identity)
}
let child1 = new Child('longhang'.12.'son')
Copy the code
Let’s print child1. It looks like this
Step 3: Inherit properties and methods from the stereotype
Above we talked about the properties of the inheritance instance, now we talk about the properties and methods of the inheritance prototype, for example, we fairy ah inherit say method.
Function Parent(name, age, identity) {this.name = name; this.age = age; this.identity = identity; } parent.prototype. Say = function () {console.log('identity' + this.identity)} identity) { Parent.call(this, name, age, identity) }Copy the code
Prototype = Parent (‘ say ‘, ‘say’, ‘say’, ‘say’)
This does allow child instances to access the say method via __proto__, but there is a problem. When we want to add a marriage method to the child, the Parent can also call the marriage method. So this is problematic, but we just need to tweak it a little bit, as follows.
Child’s __proto__ points to an empty object, but the empty object’s __proto__ points to Parent’s prototype.
// Parent constructor
function Parent(name, age, identity) {
this.name = name;
this.age = age;
this.identity = identity;
}
Parent.prototype.say = function () {
console.log('identity' + this.identity)
}
// subconstructor
function Child(name, age, identity) {
Parent.call(this, name, age, identity)
}
// Create an empty object with its __proto__ pointing to Parent's prototype
let tempObj = Object.create(Parent.prototype);
// The prototype of Child points to the empty object
Child.prototype = tempObj;
Copy the code
summary
1 inheritance is essentially giving a subclass everything its parent class has
Instance attributes are inherited by calling the parent class’s constructor
The inheritance of properties and methods on stereotypes is to first create an empty object __proto__ to the parent stereotype, and then have the subclass’s prototype point to the empty object