js原型链

深入理解js原型链

Posted by Jeremy on April 29, 2019

关于js原型链的理解

原型链概念

ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原 型让一个引用类型继承另一个引用类型的属性和方法构造函数、原型和实例的关系:每 个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型 对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的 原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数 的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实 例与原型的链条。这就是所谓原型链的基本概念。

对象分为函数对象和普通对象

了解原型链之前先了解js里的对象,ECMA-262 把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲, 这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射 到一个值。 正因为这样(以及其他将要讨论的原因),我们可以把 ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数。

js的内置对象Object、Function、Array、Date等都是函数对象,Function的实例也都是函数对象,其他内置对象的 实例都是普通对象

理解prototype和__proto__

所有的对象都有一个隐式属性__proto__(IE浏览器不支持),它是一个普通对象

所有的函数都有一个prototype属性,该属性也是一个普通对象;

所有的函数都是Function的实例,他们的默认原型都是Object的实例

特别注意:任何内置函数对象本身的__proto__都指向Function的原型对象(因为所有的函数都是Function的实例)

console.log(Function.__proto__ === Function.prototype)   //true    
console.log(Object.__proto__ === Function.prototype)     //true
console.log(Date.__proto__ === Function.prototype)      //true
console.log(Array.__proto__ === Function.prototype)     //true

通过例子深入理解

//构造函数
function Person(name){
   this.name = name      
}
Perosn.prototype.name = "sang"
Person.prototype.sayName = function(){
   alert(this.name)
}
var perosn = new Person("Jeremy")   //实例化构造函数Person   
person.sayName()    //  Jeremy >   person是构造函数Perosn的实例对象,对象都有__proto__属性,在打印台打印 person对象  

可以看到perosn对象有自己的name属性和__proto__属性,该属性是一个普通对象,指向构造函数Person的原型

我们打印一下构造函数Person.prototype,可以看出此时的 Person.prototype和person.proto__是一样的都是指向函数Person的原型对象 所以说明 person包含一个指针指向构造函数Person的原型对象 即 person.__proto === Person.prototype

只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性(该属性指向构造函数Person本身),这个属性包含一个指向 prototype 属性所在函数的指针 所以 所以 Person.prototype.constructor.prototype === Person.prototype 打印 Person.prototype.constructor.prototype 会指向原型对象 原型搜索机制。读取模式访问一个实例属性时,首先会在实例中搜索该属性。如果没有找到该属性,则会继续搜索实例的原型。在通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。就拿上面的例子来说,调用 person.name会经历三个搜索步骤:1)搜索实例;2)搜索 Person.prototype; 最后一步才会找到该方法。在找不到属性或方法的情况下,搜索过 程总是要一环一环地前行到原型链末端才会停下来。

通过一张图来展示原型链