文章目錄
- 函數的prototype
- 顯示原型與隐式原型
- 原型鍊
- 構造函數/原型/執行個體對象的關系
函數的prototype
- 函數的prototype屬性
- 每個函數都有一個prototype屬性, 它預設指向一個Object空對象(即稱為: 原型對象)
- 原型對象中有一個屬性constructor, 它指向函數對象
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yMyUTO0YzYwADZ1EzMmNWZyYzXzEDOzgTM1AzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
也就是說函數與函數的原型對象有一個互相引用的關系
- 給原型對象添加屬性(一般都是方法)
- 作用: 函數的所有執行個體對象自動擁有原型中的屬性(方法)
證明:
<script type="text/javascript">
// 每個函數都有一個prototype屬性, 它預設指向一個Object空對象(即稱為: 原型對象)
console.log(Date.prototype, typeof Date.prototype)
function Fun () {//alt + shift +r(重命名rename)
}
console.log(Fun.prototype) // 預設指向一個Object空對象(沒有我們的屬性)
// 原型對象中有一個屬性constructor, 它指向函數對象
console.log(Date.prototype.constructor===Date)
console.log(Fun.prototype.constructor===Fun)
//給原型對象添加屬性(一般是方法) ===>執行個體對象可以通路
Fun.prototype.test = function () {
console.log('test()')
}
var fun = new Fun()
fun.test()
</script>
顯示原型與隐式原型
- 每個函數function都有一個prototype,即顯式原型(屬性)
- 每個執行個體對象都有一個__proto__,可稱為隐式原型(屬性)
- 對象的隐式原型的值為其對應構造函數的顯式原型的值
- 記憶體結構(圖)
- 總結:
- 函數的prototype屬性: 在定義函數時自動添加的, 預設值是一個空Object對象
- 對象的__proto__屬性: 建立對象時自動添加的, 預設值為構造函數的prototype屬性值
- 程式員能直接操作顯式原型, 但不能直接操作隐式原型(ES6之前)
例如:
<script type="text/javascript">
//定義構造函數
function Fn() { // 内部語句: this.prototype = {}
}
// 1. 每個函數function都有一個prototype,即顯式原型屬性, 預設指向一個空的Object對象
console.log(Fn.prototype)
// 2. 每個執行個體對象都有一個__proto__,可稱為隐式原型
//建立執行個體對象
var fn = new Fn() // 内部語句: this.__proto__ = Fn.prototype
console.log(fn.__proto__)
// 3. 對象的隐式原型的值為其對應構造函數的顯式原型的值
console.log(Fn.prototype===fn.__proto__) // true
//給原型添加方法
Fn.prototype.test = function () {
console.log('test()')
}
//通過執行個體調用原型的方法
fn.test()
</script>
原型鍊
原型鍊
- 通路一個對象的屬性時,
- 先在自身屬性中查找,找到傳回
- 如果沒有, 再沿着__proto__這條鍊向上查找, 找到傳回
- 如果最終沒找到, 傳回undefined
- 别名:隐式原型鍊
- 作用: 查找對象的屬性(方法)
注意:
/*
1. 函數的顯示原型指向的對象預設是空Object執行個體對象(但Object不滿足)
*/
console.log(Fn.prototype instanceof Object) // true
console.log(Object.prototype instanceof Object) // false
console.log(Function.prototype instanceof Object) // true
/*
2. 所有函數都是Function的執行個體(包含Function)
*/
console.log(Function.__proto__===Function.prototype)
/*
3. Object的原型對象是原型鍊盡頭
*/
console.log(Object.prototype.__proto__) // null
構造函數/原型/執行個體對象的關系
例一:
var o1 = new Object();
var o2 = {};
例二:
function Foo(){ }
這張圖有幾個注意點:
- Foo的構造函數的__proto__指向Function的原型對象,因為執行個體對象的__proto__永遠指向構造函數的prototype。
- Function自己也是Function的執行個體對象,既然是對象那麼就有__proto__屬性,根據執行個體對象的__proto__永遠指向構造函數的prototype,我們可以知道Function的__proto__指向Function的原型對象。
- Object的構造函數是Function的執行個體對象,同樣也根據執行個體對象的__proto__永遠指向構造函數的prototype,是以Object的構造函數的__proto__指向Function的原型對象。