在JS中,函数是一类特殊的对象,所有函数在创建的时候,都会内置一个对象prototype,这个就是我们常说的原型,因为是对象,所以也称原型对象。
function A(){}
console.log(A.prototype) // {...} 里面有许多的属性和方法
// 创建A的时候默认内置
// 只有函数对象才会默认有
那啥是 __proto__?
每个对象都有一个__proto__,指向构造它的函数对象的prototype。
__proto__也称为隐式原型
也就是说,函数有prototype,对象有__proto__。
let a = {}
console.log(a.__proto__) // 是对象就会有一个__proto__
function B(){}
let b = new B() //创建一个构造函数B的实例对象
console.log(b.__proto__) //实例对象也是对象
对象中都有一个constructor,指向创建对象的构造函数
function B(){}
let b = new B()
b.constructor === B // true
现在我们把原型梳理巩固一下
function B(){}
let b = new B()
b.__proto__ === B.prototype // true
b.constructor === B // true
//现在我们加一个构造函数A
function A(){}
A.prototype = b //让A的原型等于B的实例,即A的原型赋值b
let a = new A() //创建一个A的实例对象
//开始理思路
a.__proto__ === A.prototype //基础逻辑
//由于A.prototype === b
a.__proto__.__proto__ === B.prototype //由 b.__proto__ === B.prototype推出
a.__proto__.__proto__.__proto__ === Object.prototype // B是由Object()构建出来的
这时候我们再来理解原型链:
顾名思义,原型链就是基于原型的一条链。
在js的查找逻辑中,我们要查找对象的某个属性或者方法,会首先在自身寻找,再依次通过原型,原型的原型这种逻辑查找下去,以第一次查找到的结果为准。
晕了么?
来段代码看看
function Demo(){
this.a = 1
}
Demo.prototype.a = 2 //给构造函数的原型加一个a属性
Demo.prototype.b = 3 //给构造函数的原型加一个b属性
let demo = new Demo() //{a:1}
demo.a // 1,因为在自身上找到,不在继续查找
demo.b // 3,自身未找到,通过__proto__找到Demo.prototype,在原型上找到b === 3
demo.hasOwnProperty //自身和Demo.prototype均未找到,继续__proto__,找到Object.prototype,上面有该方法
//注意,Object.prototype已到达最顶层,Object.prototype.__proto__为null
js查找逻辑按照自身开始,沿着原型一直向上查找,形成一条基于原型的链,称为原型链