javascript原型链图解

如果没搞懂原型,就不算真懂javascript。

这篇文章是学习中对原型及原型链的理论的一个小总结,弄懂基本理论之后,在实践中加深对原型的认识和掌握。

理解以下三点对理解原型有帮助:

  1. javascript中一切都是对象,函数本身也是对象。
  2. javascript中继承机制是通过原型实现的,这点不同于java等语言通过class实现。
  3. 从顶端看原型链有助于理解,原型链最顶端是null(一),下一层是{}(二),接下来就是各种原型分支(万物),一生二,二生三,三生万物

函数对象及其 prototype 属性

function Player(name) {
  this.name = name
}

定义函数A,函数A本身也是对象,函数对象中的prototype属性指向此函数所有实例的原型(__proto__)对象,这个原型对象中有一个constructor属性,constructor属性又指向函数A这个对象本身。以上面代码为例,示意图如下:

《javascript原型链图解》 函数对象及其prototype属性

函数的所有实例中的__proto__属性都指向函数prototype属性所指向的对象

const newPlayer = new Player('tom')
//true
console.log(newPlayer.__proto__ === Player.prototype)

代码图解如下:

《javascript原型链图解》

原型链是用对象的
__proto__属性链接起来的原型对象,函数的
prototype属性和
__proto__不是一回事,
prototype指向的是函数所有实例的原型(
__proto__),而函数的
__proto__属性指向的是它自己的原型链上的原型对象。

//false
console.log(Player.__proto__ === Player.prototype);

图示如下:

《javascript原型链图解》 函数的prototype和__proto__属性

只有函数才有prototype属性,但是每个对象都有__proto__属性

函数对象本身的原型链层次关系

《javascript原型链图解》 函数的原型链层次关系

代码验证:

//result: [Function] 即图中的Function prototype对象
console.log(Player.__proto__);
//result: {} 即图中的Object prototype对象
console.log(Player.__proto__.__proto__);
//result: null
console.log(Player.__proto__.__proto__.__proto__);

函数的原型(__proto__)与函数实例的原型(__proto__)不同

验证代码如下:

//[Function]函数的原型
console.log(Player.__proto__);
//Player {}函数实例的原型,与函数的prototype相同
console.log(newPlayer.__proto__)
//false
console.log(Player.__proto__ === newPlayer.__proto__)

每个对象都有constructor属性,constructor属性指向创建这个对象的函数,所以可以通过constructor属性调用它所指向函数的prototype属性

验证代码如下:

//创建两个Player函数的实例(对象)
const player1 = new Player('tom')
const player2 = new Player('tom')
//[Function: Player]指向Player函数
console.log(player1.constructor);
//[Function: Player]指向Player函数
console.log(player2.constructor);
//true
console.log(player1.constructor === player2.constructor);
//[Function: Player]指向Player函数
console.log(player1.__proto__.constructor);
//[Function: Player]指向Player函数
console.log(Player.prototype.constructor);
//true
console.log(player1.__proto__.constructor === Player.prototype.constructor);
//函数实例的constructor属性与它的原型(__proto__)中的constructor属性相同,都指向函数对象
console.log(player1.constructor === player1.__proto__.constructor);
//Player {} 又指向了player2的(原型)`__proto__`对象
console.log(player2.constructor.prototype);
//true
console.log(player1.constructor.prototype == player2.constructor.prototype);

本文参考和使用了 從ES6開始的JavaScript學習生活 一书中的资源。

    原文作者:黄老之学
    原文地址: https://www.jianshu.com/p/447796fcd729
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞