Home  >  Article  >  Web Front-end  >  The ultimate detailed explanation of JavaScript prototypes and prototype chains_javascript skills

The ultimate detailed explanation of JavaScript prototypes and prototype chains_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:21:501062browse

The ultimate detailed explanation of JavaScript prototypes and prototype chains

1. Ordinary objects and function objects

In JavaScript, everything is an object! But the objects are also different. It is divided into ordinary objects and function objects. Object and Function are the function objects that come with JS. Here are some examples

function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
var o3 = new f1();
var o1 = {};
var o2 =new Object();
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
 console.log(typeof o3); //object
  console.log(typeof f1); //function
  console.log(typeof f2); //function
  console.log(typeof f3); //function 

In the above example, o1 o2 o3 are ordinary objects, and f1 f2 f3 are function objects. How to tell the difference is actually very simple. All objects created through new Function() are function objects, and others are ordinary objects. f1, f2, are all created through new Function() in the final analysis. Function Objects are also created through New Function().

2. Prototype object

In JavaScript, whenever an object (function) is defined, the object will contain some predefined properties. One of the properties of the function object is the prototype object prototype. Note: Ordinary objects do not have prototype, but have __proto__ attribute.

Prototype objects are actually ordinary objects (except Function.prototype, which is a function object, but it is very special. It has no prototype attribute (as mentioned earlier, function objects all have prototype attributes)). Look at the example below:

function f1(){};
console.log(f1. prototype) //f1 {}
console.log(typeof f1. prototype) //Object
console.log(typeof Function. prototype) // Function
console.log(typeof Object. prototype) // Object
console.log(typeof Function. prototype. prototype) //undefined

From the output of this sentence console.log(f1. prototype) //f1 {}, we can see that f1. prototype is an instance object of f1. When f1 is created, an instance object of it is created and assigned to its prototype. The basic process is as follows:

var temp = new f1();
f1. prototype = temp;

So, it is easy to understand why Function.prototype is a function object. As mentioned above, all objects generated by new Function () are function objects, so temp is a function object.

var temp = new Function ();
Function. prototype = temp;

What is the prototype object used for? Mainly used for inheritance. Give an example:

var person = function(name){
  this.name = name
};
person.prototype.getName = function(){
return this.name;
}
var zjh = new person(‘zhangjiahao');
zjh.getName(); //zhangjiahao

从这个例子可以看出,通过给person.prototype设置了一个函数对象的属性,那有person实例(例中:zjh)出来的普通对象就继承了这个属性。具体是怎么实现的继承,就要讲到下面的原型链了。

三.原型链

JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype。以上面的例子为例:

console.log(zjh.__proto__ === person.prototype) //true

同样,person.prototype对象也有__proto__属性,它指向创建它的函数对象(Object)的prototype

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

继续,Object.prototype对象也有__proto__属性,但它比较特殊,为null

console.log(Object.prototype.__proto__) //null

我们把这个有__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。如下图:


四.内存结构图

为了更加深入和直观的进行理解,下面我们画一下上面的内存结构图:

画图约定:

疑点解释:

1.Object.__proto__ === Function.prototype // true

Object是函数对象,是通过new Function()创建,所以Object.__proto__指向Function. prototype。

2.Function.__proto__ === Function.prototype // true

Function 也是对象函数,也是通过new Function()创建,所以Function.__proto__指向Function. prototype。

自己是由自己创建的,好像不符合逻辑,但仔细想想,现实世界也有些类似,你是怎么来的,你妈生的,你妈怎么来的,你姥姥生的,……类人猿进化来的,那类人猿从哪来,一直追溯下去……,就是无,(NULL生万物)

正如《道德经》里所说“无,名天地之始”。

3.Function.prototype.__proto__ === Object.prototype //true

其实这一点我也有点困惑,不过也可以试着解释一下。

Function.prototype是个函数对象,理论上他的__proto__应该指向 Function.prototype,就是他自己,自己指向自己,没有意义。

JS一直强调万物皆对象,函数对象也是对象,给他认个祖宗,指向Object. prototype。Object. prototype.__proto__ === null,保证原型链能够正常结束。

五.constructor

原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用

person.prototype. constructor === person //true
Function.prototype.constructor === Function //true
Object.prototype.constructor === Object //true

完善下上面的内存结构图:

有两点需要注意:

1.注意Object.constructor===Function;//true 本身Object就是Function函数构造出来的
2.如何查找一个对象的constructor,就是在该对象的原型链上寻找碰到的第一个constructor属性所指向的对象

六.总结

1.原型和原型链是JS实现继承的一种模型。

2.原型链的形成是真正是靠__proto__ 而非prototype

要深入理解这句话,我们再举个例子,看看前面你真的理解了吗?

var animal = function(){};
var dog = function(){};
animal.price = 2000;//
dog.prototype = animal;
var tidy = new dog();
console.log(dog. price) //undefined
console.log(tidy.price) // 2000

Why? Draw a memory diagram:


What does this mean? When executing dog.price, it was found that there is no price attribute. Although the animal pointed to by prototype has this attribute, it does not search along this "chain". Similarly, when tidy.price is executed, there is no such attribute, but __proto__ points to animal, and it will search along this chain. Animal has the price attribute, so tidy.price outputs 2000. It follows that the real formation of the prototype chain depends on __proro__, not prototype.

So if dog.__proto__ = animal is specified like this. That dog.price = 2000.

437fcc348f7b1c54dc1b8f8cb5743cbc1.

04c6c2c265887a55041405a81efec09aFinally, let me give you a metaphor. Although it is not very accurate, it may be helpful for understanding the prototype.

Father (function object) gave birth to an eldest son (prototype), which is your eldest brother. Your father bought a lot of toys for your eldest brother. When you were born, the family bond between you (__proto__) will make You automatically own your big brother's toys. Similarly, if you have an older son first and buy him a lot of toys, when you have another son, your younger son will naturally have all the toys of your older son. Whether they will fight or not is none of our business.

So, you inherited it from your eldest brother, which proves the saying "A brother is like a father"

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