信我一次这次真的能搞懂原型链
不说废话首先咱们先搞懂两个概念
prototype
原型或者称为原型对象
- 特点1.prototype是函数的属性
- 特点2.prototype是个对象
- 特点3.创建函数的时候都会默认在该函数上添加prototype属性
上述这三点没有疑问吧,如果有疑问请看下方例子
function test(){
this.aa = 1
}
console.log(test.prototype) //证明特点1
console.log(test.prototype instanceof Object) //true 证明特点2
console.log(test) //打印出的是个函数体看不出来
console.dir(test) /** 打印出函数对象ƒ test()
arguments: null
caller: null
length: 0
name: "test"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM116:1
[[Scopes]]: Scopes[1] **/
//证明特点3
__proto__
隐式原型
- 特点1:它是对象上的一个属性
- 特点2:指向构造函数的prototype 如果有疑问,看下面的例子 console.dir({}) //结果可以在浏览器控制台跑一下,我这里就不贴了,反正看到结果就知道我刚才说的那两个特点没啥毛病
上面的基本概念看完之后咱们来个例子,就能明白什么是原型链了。
仍然使用test函数
function test(){
this.a = 1
}
const obj = new test()
console.log(obj)
//可以看到obj这个对象上的__proto__指向了test的prototype属性
console.log(obj.__proto__ ===test.prototype) //true
此时我们将test.prototype对象加个属性
test.prototype.b =2
console.log(obj.b) //2
你看我们并没有在obj这个对象上增加属性b,但是通过原型链,我们可以打印出obj.b
的值
然后因为test.prototype
是个对象,那既然是对象那肯定存在__proto__
属性也即是
console.log(test.prototype.__proto__ ===Object.prototype) //true
同理,我们此时在Object.prototype
对象上加个属性c
Object.prototype.c = 3
console.log(obj.c) //3
说到这,此时原型链还没停止,因为我们发现Object.prototype
也是对象,那是对象就存在__proto__
属性,所以我们就继续打印
console.log(Object.prototype.__proto__) //null
此时发现打印出为null,到这原型链就算停止了。
上述的文字可以转化为类对象更好理解
obj = {
a:1
__proto__ = test.prototype = {
b:2
__proto__ = Object.prototype = {
c:3
__proto__ = null
}
}
}
上面通过类对象的形式便于理解原型链。
转载自:https://juejin.cn/post/7382151765381578771