关于前端:一文搞懂原型和原型链

8次阅读

共计 1941 个字符,预计需要花费 5 分钟才能阅读完成。

在理解原型和原型链之前首先得明确它俩是什么货色:

原型: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
......

正文完
 0