3

一文搞懂原型和原型链 - fanction

 1 year ago
source link: https://www.cnblogs.com/wang-fan-w/p/17277765.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在了解原型和原型链之前首先得明确它俩是什么东西:

原型:prototype
又称显示原型
1、原型是一个普通对象
2、只有构造函数才具备该属性
3、公有属性可操作

隐式原型:__proto__
1、只有对象(普通对象、函数对象)具备
2、私有的对象属性,不可操作

有了上面的概念之后,我们再来探讨一下什么是原型和原型链。

原型(显示原型) : prototype

我们定义一个字符串变量的时候,该字符串本身是不具备任何方法的,但是可以调用字符串方法。

let str = 'hello'  // new String()
console.log(str);
console.log(str.length);

在这里插入图片描述

其实我们在定义一个字符串变量的时候,隐式的实例化了new String()这个构造函数,所以我们才可以使用字符串方法。

 console.log(new String());

在这里插入图片描述

这个length就是String的原型方法ptototype,字符串本身有没有这个方法不重要,字符串的原型上有个方法就可以了。
原型的本质是一个普通对象,所以我们可以利用对象.属性的方式调用方法。
如果我们用字符串调用一个DCodes(),该方法在字符串属性上没有并不存在,调用该方法会报错。
在这里插入图片描述
我们给String的原型添加一个DCodes方法,字符串就可以调用该方法了。

String.prototype.DCodes = function(){
       console.log('你好DCodes');
}
str.DCodes() // 你好DCodes

利用原型可以干什么呢?上面也说了,构造函数才具备原型,我们创建一个构造函数,可以通过实例化这个构造函数来调用原型方法和原型属性。

// 构造函数
function Person(){
         this.name = '东方不败'
}
let per = new Person()
console.log(per);

在这里插入图片描述
原型的本质是一个对象,那么给Person这个原型添加一个方法

function Person(){
         this.name = '东方不败'
}
Person.prototype.sum = function(a,b){return a + b}
let per = new Person()
console.log(per);
console.log(per.sum(1,2));

在这里插入图片描述
构造函数记录了当前原型对象产生的归属,原型是基于那个构造函数构建的,那么constructor指向的就是那个构造函数,这里的constructor指向的就是Person()函数。


__proto__隐式原型

隐式原型只有对象(普通对象、函数对象)才具备,并且隐式原型是一个私有的对象属性,不可操作。
上面也提到过,我们定义了一个字符串,实际上是隐式的new String()String()的原型上有length,所以字符串可以调用length方法,显示原型prototype是构造函数才具备的,普通对象是没有的,那么普通对象是怎么调用构造函数的原型方法的呢?答案就是普通对象具有隐式原型,隐式原型全等于显示原型

let hello = 'hello'
console.log(hello.__proto__ === String.prototype);  // true

在这里插入图片描述
也就是说,普通对象的隐式原型__proto__等于构造函数的显示原型prototype,普通对象就可以调用构造函数的原型方法。
谷歌浏览器中,隐式原型__proto__的写法为: [[Prototype]]
在这里插入图片描述
到这里就构成了原型链,用字符串调用字符串方法的时候,字符串会在__proto__寻找对应的字符串方法,__proto__等于prototype,也就是String()构造函数,如果String()的构造函数没有该方法,那么String()会继续向上寻找,原型prototype是一个对象,那么对象就会有隐式原型__proto__String()的隐式原型__proto__Object(),然后会在Object()的原型prototype上寻找,如果Object()的原型prototype上不存在该属性,那么就会通过隐式原型__proto__继续向上寻找,直到找到对应的方法为止,如果没有找到,那么就会报错,该方法不存在。(这一段需要好好理解)
这样向上寻找,最终总会有尽头,万物的原型终点是谁呢?
字符串、数组、构造函数的原型最终都会指向Object,而Object的原型指向的是null

在这里插入图片描述
console.log(Object.prototype);
在这里插入图片描述

最后我们来看一下prototype、__proto__之间的关系:

__proto__ === prototype 
prototype == {}
{}.__proto__ == Object.prototype
......

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK