preface

function Weather(temperature, moisture) {
	this.temperature = temperature
	this.moisture = moisture
}

Weather.prototype.getTemperature = function() {
	return this.temperature
}

Weather.prototype.getMoisture = function() {
	return this.moisture
}
Copy the code

Before ES6 classes, the way the front end wrote “classes” was in the form of constructors. The “construct call” to the constructor Weather instantiates a new object Weather:

const weather = new Weather('25 ° C'.'79%')
Copy the code

Get the weather object in the browser console and it should look like this:

The two functions originally defined on weather. prototype are in the __proto__ attribute of this object, so where does this attribute come from? What is its relationship to weather.prototype? Why does __proto__ refer to an object with a __proto__ attribute inside it? I’ll explain them all.

What is the prototype

As we all know, functions are object types in JavaScript. Since they are objects, we can define properties or methods on the object, for example:

function getCount() {
	return getCount.count
}

getCount.count = 1

console.log(getCount())  / / 1
Copy the code

In this case, defining the prototype attribute on the Weather function is not a strange thing. The question is, what is this prototype?

All JavaScript functions (except the arrow function) have the Prototype built-in property that holds the object that is the prototype of the new object instantiated by the constructor.

Archetypes and functions

JavaScript is an object-oriented programming language based on prototype design. When facing any object operation in the program, there will always be another object associated with it to help do delegate processing, which is the prototype. Object’s special built-in attribute [[Prototype]] holds a reference to the Prototype.

Different browser vendors have different private implementations of how to get this property, such as Chrome, which gets the object prototype from the __proto__ property. ES6 designed a new API – Object.getProtoTypeof (Object) to get the prototype of a specified Object.

As mentioned earlier, archetypes play the role of delegation, so how does this work? Look at this code:

console.log(weather.getTemperature())  / / '25 ° C'
Copy the code

An object’s [[Get]] action is triggered when a property or method is referenced to any object in a program, such as weather.getTemperature() in the code above. For the default [[Get]] operation, the object itself is checked to see if it has the property or method, and if so, it is used. If not, go up to [[Prototype]] to find the property or method.

The weather object does not have a getTemperature method, so you have to look inside the object that its __proto__ property holds. __proto__ holds object prototypes, so when an object looks for a property or method that doesn’t exist on its own, it will look for the corresponding prototype again. This behavior is also called behavior delegation.

Instance and constructor relationships

The constructor’s prototype property is the prototype of the instantiated object, which means that weather.__proto__ === weather. prototype is true, which indicates the relationship between the instance and the constructor’s Prototype property. So how does Prototype relate to the constructor itself?

Prototype saves an object with the constructor attribute pointing to the constructor itself. That may not be the case:

function Weather(temperature, moisture) {
    this.temperature = temperature
    this.moisture = moisture
}

const weather = new Weather('25 ° C'.'79%')
Copy the code

Change the code to look like this, discard the display definition of prototype, and still find that the __proto__ for weather in the console contains the constructor attribute pointing to the weather constructor. Next, continue to change the code as follows:

Weather.prototype = {
	getTemperature: function() {
		return this.temperature
	},
	
	getMoisture: function() {
		return this.moisture
	}
}
Copy the code

The constructor attribute is missing from the __proto__ console. This is because prototype’s default object was changed by the code, so the associated default attribute is missing. The remedy is to add constructor to the display. Although the constructor property is somewhat related to the constructor, it is important to recognize that the relationship between the property and the constructor is fragile and subject to human manipulation.

So far, the relationship between instance, constructor, and Prototype is as follows:

graph LR A[Weather] -- prototype --> B[Weather.prototype] B[Weather.prototype] -- constructor --> A[Weather] A[Weather] -- instantiate - > C [weather] - [weather] C __proto__ - > B/weather. The prototype

Prototype chain

Now to the last question, why does __proto__ have another __proto__ attribute inside it? First, the constructor’s prototype is also an object. This object is created in two ways, one is created by default in the program, and the other is the literal 1 in the code. But when the compiler finally handles both scenarios, it calls the Object constructor to create the Object, so weather.prototype. __proto__ refers to Object.prototype. Object. Prototype is an Object, so whose __proto__ points to?

Type Object.prototype on the browser console to get the following screenshot:

Object. Prototype points to an Object that contains methods that are common to all objects, and its __proto__ attribute is slightly special. In other words, setters are automatically called when object.prototype. __proto__ is fetched, resulting in null.

Therefore, after adding the Object constructor to the previous diagram:

graph LR A[Weather] -- prototype --> B[Weather.prototype] B[Weather.prototype] -- constructor --> A[Weather] A[Weather] -- instantiate - > C [weather] - [weather] C __proto__ - > B/weather. The prototype B/weather. The prototype - __proto__ -- -- > F[Object.prototype] E[Object] -- prototype --> F[Object.prototype] F[Object.prototype] -- constructor --> E[Object] F[Object.prototype] -- __proto__ --> G[null]

Hidden in this diagram is a chain of prototypes linked to each other by __proto__ :

weather -> Weather.prototype -> Object.protype -> null
Copy the code

The role of the prototype chain is consistent with the role of the prototype, facilitating the behavior of objects on the chain delegate.

conclusion

  1. constructionalprototypeA property is a stereotype of an instantiated object, whose role is embodied in the behavior delegate.
  2. Each object has its own prototype object (there are special cases), and the prototype object has its own prototype, which is nested layer upon layer to form the prototype chain, and the prototype chain ends innull.

Along with the written

There were a lot of jokes to type out, but I’d better think about it when I touch the keyboard. I have tried blogging countless times before and failed to stick to it. I don’t know if I can stick to it this time.

This article is still a prototype of the familiar JavaScript cliche, mixed with some poor understanding of my own. If I can help you, it’s the best. If I can’t help you, I’m sorry!

I hope I can write a second column, that’s it!!

Finally finally, may wenchuan earthquake suffering people, the dead rest in peace, the living so.


  1. A literal is a representation of a fixed value in source code. For example,const a = 10The inside of the10Literals, literals of objects{} 。↩