JavaScript深刻之——原型与原型链

很长一段时间对JS的原型与原型链理解的很模糊,而想学好JS,原型与原型链倒是绕不开的话题,因此只好进行对其进行一个梳理。javascript

理解原型和原型链,需理解三个重要的属性: prototype、__proto__、constructorjava

 

prototype函数

JavaScript函数中,每个函数都有一个prototype属性,叫原型对象。spa

代码示例:prototype

function Person(){

}

Person.prototype.name = 'zhangsan'
let person = new Person()

console.log(person.name)    // zhangsan

上面的代码中,建立了一个构造函数Person,并在它的原型上添加一个属性name为zhangsan, 而后再建立了实例对象person,那么这个实例对象上也有name属性,打印输出“zhangsan”3d

能够看出:code

Person这个函数的prototype属性指向了一个对象,即:Person.prototype 也是一个对象,这个对象正是调用该构造函数而建立的实例的原型,即person的原型。对象

方便理解,咱们进行拆解:blog

1.建立了构造函数Person

2.使用new关键字进行调用

3.调用获得了实例person

4.实例和原型的关系:person的原型就是Person.prototype

  

那什么是原型呢?能够这样理解:每个JavaScript对象(null除外)在建立的时候就会与之关联另一个对象,这个对象就是咱们所说的原型,而每个对象都会从原型"继承"属性。继承

咱们用一张图表示构造函数和原型之间的关系:

构造函数和实例原型之间的关系咱们已经梳理清楚了,那怎么表示实例与原型,也就是person和Person.prototype之间的关系呢?

 

__proto__

其实每个JavaScript对象(除了null)都有一个属性,叫__proto__,这个属性会指向该对象的原型。

代码示例:

function Person(){

}

let person = new Person()
console.log(person.__proto__ === Person.prototype)   // true

构造函数Person的实例对象person,有个属性叫__proto__,这个属性指向原型,即Person.prototype。

补全上面的关系图:

Q:原型是否有属性指向构造函数或者实例对象呢?

 

constructor

代码示例:

function Person() {

}
let person = new Person()
console.log(Person === Person.prototype.constructor); // true

 

继续完善关系图:

原型的constructor指向构造函数,但没有属性指向实例,由于可能有多个实例。

其实 person 中并无constructor 属性,当不能读取到constructor属性时,会从 person 的原型也就是 Person.prototype中读取

console.log(person.constructor === Person)   // true
console.log(person.constructor === Person.prototype.constructor)  // true

  

  

 实例与原型

当读取实例的属性时,若是找不到,就会查找与对象关联的原型中的属性,若是还查不到,就去找原型的原型,一直找到最顶层为止。

代码示例:

 function Person() {

}

Person.prototype.name = 'zhangsan';

let person = new Person();

 person.name = 'lisi';
 console.log(person.name) // lisi

delete person.name;
console.log(person.name) // zhangsan

 

new建立了一个实例对象person,有个属性name值为“lisi”,当咱们把删除了这个name属性后,依然可以打印出“zhangsan”,实际状况是从 person 实例对象中找不到 name 属性,就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找,幸运的是咱们找到了 name 属性,结果为 zhangsan

 

原型的原型

代码示例:

Object.prototype.name = 'wangwu'

function Person(){

}

let person = new Person()
		
		
console.log(person.name)   // wangwu

Person 的实例对象person,自己没有name属性值,全部会去原型上找,Person.prototype上也没有,就去原型的原型上找,即:Object.prototype,有一个name为“wangwu”的属性,全部输出“wangwu”

其实原型对象就是经过Object构造函数生成的,结合以前咱们所说的,实例的__proto__指向构造函数的 prototype 因此咱们再丰富一下咱们的关系图:

 

原型链

那Object.prototype 的原型呢?Object是根节点的对象,再往上查找就是null,咱们能够打印:

  console.log(Object.prototype.__proto__ === null) // true

 咱们将null也加入关系图,就比较完整了:

 

上面的person实例对象到null的这条线即为原型链。

 

咱们还能够把大Function加上

console.log(Person.constructor === Function)  // true
console.log(obj.__proto__ === Object.prototype) // true
console.log(obj.__proto__.constructor === Object) /// true
console.log(obj.__proto__.constructor.__proto__ === Function.prototype) // true
console.log(obj.__proto__.constructor.__proto__.constructor === Function) // true
console.log(Person.__proto__ === Function.prototype) // true console.log(Object.__proto__ === Function.prototype) // true

 从网上找了张图,如今再去理解原型与原型链,就好理解了吧

相关文章
相关标签/搜索