一文搞懂原型和原型链 - fanction
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.
在了解原型和原型链之前首先得明确它俩是什么东西:
原型: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
......
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK