Home  >  Article  >  Web Front-end  >  A brief analysis of the relationship between __proto__ and prototype in JavaScript

A brief analysis of the relationship between __proto__ and prototype in JavaScript

零到壹度
零到壹度Original
2018-03-22 11:37:151071browse

This time I will give you a brief analysis of the relationship between __proto__ and prototype in JavaScript. The following is a practical case. Follow the editor to take a look.

1. The __proto__ of all constructors/functions points to Function.prototype, which is an empty function (Empty function)

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 (build-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

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

The "all constructors/functions" mentioned above certainly include custom ones. As follows

// 函数声明
function Person() {}
// 函数表达式
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 typeof XXX.prototype prototype of "function". The prototype of other constructors is an object. For example:

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 was also mentioned above that it is an empty function, let’s take a look at alert(Function.prototype).

Now that we know that the __proto__ of all constructors (including built-in and custom) are Function.prototype, then who is the __proto__ of Function.prototype?

I believe you have all heard that functions in JavaScript are also first-class citizens, so how can you show this? As shown below

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

This shows that all constructors are also ordinary JS objects, and attributes can be added/removed 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?

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 above tests the __proto__ of all built-in constructors and custom constructors, below Let’s take a look at who the __proto__ of the instance objects of all these constructors points to?

Let’s first look at the built-in constructor of the JavaScript engine

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

Then look at the custom constructor. A Person is defined here

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, p The internal prototype always points to the prototype of its constructor Person.

Each object has a constructor attribute, and its constructor can be obtained, so the following print results are also identical

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

The above Person does not add attributes or methods to its prototype, here Add a getName method to its prototype

function Person(name) {
this.name = name
}
// 修改原型
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 that p.__proto__, Person.prototype, and p.constructor.prototype are all identical, that is, they all point to the same object.

If you set the prototype in another way, the result will be somewhat different

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

Here, Person.prototype is directly rewritten (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 object literals points to the root constructor Object, Object.prototype is an empty object {}, {} is naturally the same as {getName: function(){}} is not equal. As follows

var p = {}
console.log(Object.prototype) // 为一个空的对象{}
console.log(p.constructor === Object) // 对象直接量方式定义的对象其constructor为Object
console.log(p.constructor.prototype === Object.prototype) // 为true,不解释

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.

var p = {}
var __proto__ = Object.getPrototypeOf(p)
console.log(__proto__ === Object.prototype) // true

The above is the detailed content of A brief analysis of the relationship between __proto__ and prototype in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

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