如果没搞懂原型,就不算真懂javascript。
这篇文章是学习中对原型及原型链的理论的一个小总结,弄懂基本理论之后,在实践中加深对原型的认识和掌握。
理解以下三点对理解原型有帮助:
- javascript中一切都是对象,函数本身也是对象。
- javascript中继承机制是通过原型实现的,这点不同于java等语言通过class实现。
- 从顶端看原型链有助于理解,原型链最顶端是null(一),下一层是{}(二),接下来就是各种原型分支(万物),
一生二,二生三,三生万物
函数对象及其 prototype 属性
function Player(name) {
this.name = name
}
定义函数A,函数A本身也是对象,函数对象中的prototype属性指向此函数所有实例的原型(__proto__
)对象,这个原型对象中有一个constructor属性,constructor属性又指向函数A这个对象本身。以上面代码为例,示意图如下:
函数的所有实例中的__proto__
属性都指向函数prototype
属性所指向的对象
const newPlayer = new Player('tom')
//true
console.log(newPlayer.__proto__ === Player.prototype)
代码图解如下:
原型链是用对象的
__proto__
属性链接起来的原型对象,函数的prototype
属性和__proto__
不是一回事,prototype
指向的是函数所有实例的原型(__proto__
),而函数的__proto__
属性指向的是它自己的原型链上的原型对象。
//false
console.log(Player.__proto__ === Player.prototype);
图示如下:
函数的prototype和__proto__属性
只有函数才有prototype属性,但是每个对象都有
__proto__
属性
函数对象本身的原型链层次关系
函数的原型链层次关系代码验证:
//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學習生活 一书中的资源。
网友评论