Home  >  Article  >  Web Front-end  >  In-depth understanding of the relationship between __proto__ and prototype in JavaScript_Basic knowledge

In-depth understanding of the relationship between __proto__ and prototype in JavaScript_Basic knowledge

WBOY
WBOYOriginal
2016-05-16 17:47:26857browse

Here we discuss the relationship between the object's internal prototype (__proto__) and the constructor's prototype (prototype).
1. The __proto__ of all constructors/functions points to Function.prototype, which is an empty function (Empty function)

Copy code The code is as follows:

Number.__proto__ === Function.prototype // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === Function. prototype // true
RegExp.__proto__ === Function.prototype // true
Error.__proto__ === Function.prototype // true
Date.__proto__ === Function.prototype // true

There are a total of 12 built-in constructors/objects in JavaScript (JSON is newly added in ES5). Here are 8 accessible constructors. The rest such as Global cannot be accessed directly, Arguments are only created by the JS engine when the function is called, Math and JSON exist in the form of objects and do not require new. Their __proto__ is Object.prototype. As follows
Copy code The code is as follows:

Math.__proto__ === Object.prototype // true
JSON.__proto__ === Object.prototype // true

The "all constructors/functions" mentioned above certainly include custom ones. As follows
Copy code The code is as follows:

// Function declaration
function Person() {}
// Function expression
var Man = function() {}
console.log(Person.__proto__ === Function.prototype) // true
console.log(Man. __proto__ === Function.prototype) // true

What does this mean?
All constructors come from Function.prototype, even the root constructor Object and Function itself. All constructors inherit the properties and methods of Function.prototype. Such as length, call, apply, bind (ES5).
Function.prototype is also the only prototype whose typeof XXX.prototype is "function". The prototype of other constructors is an object. As follows
Copy code The code is as follows:

console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype) // object
console.log(typeof Number.prototype) // object
console.log(typeof Boolean.prototype) // object
console .log(typeof String.prototype) // object
console.log(typeof Array.prototype) // object
console.log(typeof RegExp.prototype) // object
console.log(typeof Error .prototype) // object
console.log(typeof Date.prototype) // object
console.log(typeof Object.prototype) // object

Oh, it’s also mentioned above It turns out that it is an empty function, look at alert(Function.prototype).
We know that the __proto__ of all constructors (including built-in and custom) are Function.prototype, so who is the __proto__ of Function.prototype?
I believe you have heard that functions in JavaScript are also first-class citizens, so where can you show this? As follows
Copy the code The code is as follows:

console.log(Function.prototype.__proto__ == = Object.prototype) // true

This shows that all constructors are also ordinary JS objects, and you can add/remove attributes to the constructor. At the same time, it also inherits all methods on Object.prototype: toString, valueOf, hasOwnProperty, etc.
Who is the __proto__ of Object.prototype?
Copy code The code is as follows:

Object.prototype.__proto__ === null // true

has reached the top and is null.
2. The __proto__ of all objects points to the prototype of its constructor
The __proto__ of all built-in constructors and custom constructors have been tested above. Let’s take a look at the __proto__ of all the instance objects of these constructors. Who does _proto__ point to?
Let’s take a look at the built-in constructor of the JavaScript engine first
Copy the code The code is as follows:

var obj = {name: 'jack'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception')
console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype) // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype) // true
console.log(err.__proto__ === Error.prototype) // true

Look at the custom constructor again, a Person is defined here
Copy code The code is as follows:

function Person(name) {
this.name = name
}
var p = new Person('jack ')
console.log(p.__proto__ === Person.prototype) // true

p is an instance object of Person, and the internal prototype of p always points to its constructor Person. prototype.
Each object has a constructor attribute that can get its constructor, so the following printed results are also identical
Copy code The code is as follows:

function Person(name) {
this.name = name
}
var p = new Person('jack')
console .log(p.__proto__ === p.constructor.prototype) // true

The Person above does not add attributes or methods to its prototype. Here, add a getName method to its prototype
Copy code The code is as follows:

function Person(name) {
this.name = name
}
// Modify prototype
Person.prototype.getName = function() {}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true

You can see p.__proto__ and Person.prototype, p.constructor.prototype are all identical, that is, they all point to the same object.
If you set up the prototype in another way, the results will be a little different
Copy the code The code is as follows:

function Person(name) {
this.name = name
}
// Override prototype
Person.prototype = {
getName: function() {}
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p. constructor.prototype) // false

Person.prototype is directly rewritten here (note: the previous example is to modify the prototype). The output shows that p.__proto__ still points to Person.prototype, not p.constructor.prototype.
This is also easy to understand. What is assigned to Person.prototype is an object literal {getName: function(){}}. The constructor of an object defined using the object literal method points to the root constructor. Object, Object.prototype is an empty object {}, {} is naturally different from {getName: function(){}}. As follows
Copy the code The code is as follows:

var p = {}
console.log (Object.prototype) // It is an empty object {}
console.log(p.constructor === Object) // The constructor of an object defined in the object literal mode is Object
console.log(p .constructor.prototype === Object.prototype) // If true, no explanation is given

The __proto__ used in the above code is currently not supported in IE6/7/8/9. In IE9, you can use Object.getPrototypeOf(ES5) to get the internal prototype of an object.
Copy code The code is as follows:

var p = {}
var __proto__ = Object .getPrototypeOf(p)
console.log(__proto__ === Object.prototype) // true
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn