共计 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
......