JS function 是函數也是對象, 淺談原型鏈
JS 唯一支持的繼承方式是通過原型鏈繼承, 理解好原型鏈非常重要, 我記錄下我的理解
1. 前言
-
new 出來的實例有 _proto_ 屬性, 並且指向其構造函數的 prototype 對象
function Person(){} const person = new Person(); person.__proto__ === Person.prototype // true
-
所有 new 出來的實例有 _proto_ 屬性, 所有函數有 prototype 屬性
-
不要小看任何一個對象, 這個對象有可能是一個函數; 不要小看任何一個函數, 這個函數有可能也是一個對象
-
只要是對象, 一定就有相應的構造函數 ( 除了 Object 的原型對象找不到 )
2. 有趣的部分
- function 是函數, 但也是對象
- Object 是函數, 但也是對象
- 看一個對象是不是函數, 就看它有沒有 prototype 屬性, 像原型對象沒有, 它就只是單純的對象, 不是函數 ( 原型對象無原型 )
- Function 是函數, 也是對象, 並且它作為對象的 _proto_ 屬性 等於 它作為函數的 prototype 屬性, 這說明, 它 自己創建自己
3. 解釋
-
以這個為例
function Person(){} const person = new Person();
-
function 是函數, 但也是對象
- 是函數
Person.prototype // {constructor: ƒ ...} Person.prototype.constructor === Person // true
這說明 Person 是函數, 有原型, 原型的 constructor 指向自己
- 是對象
Person.__proto__ // ƒ () { [native code] } Person.__proto__ === Function.prototype //true
這說明 Person 是對象, 相當於
Person = new Function()
, 有沒有那味了呢
-
原型對象是單純的對象, 不是函數
Person.prototype.prototype // undefined 不是函數, 無原型 Person.prototype.__proto__ // {constructor: ƒ...} Person.prototype.__proto__ === Object.prototype // true
原型對象無原型, 說明原型對象就只是一個對象, 是對象肯定就有構造函數, 其構造函數是 Object, 相當於
Person.prototype = new Object()
-
Object 是函數, 但也是對象
Object.prototype // {constructor: ƒ ...} 是函數, 有原型 Object.prototype.__proto__ // null 所有對象都有其構造函數, Object 原型對象例外 Object.__proto__ // ƒ () { [native code] } Object 是對象 Object.__proto__ === Function.prototype // true
Object 有原型對象, 說明它是個函數, 並且它的原型是唯一一個找不到構造函數的; Object 是對象, 有自己的構造函數, 並且它的構造函數是 Function. 相當於
Object = new Function()
-
Function 是函數, 也是對象, 並且它自己創建自己
Function.prototype // ƒ () { [native code] } 是函數 Function.__proto__ // ƒ () { [native code] } 是對象 Function.__proto__ === Function.prototype // true Function.prototype.__proto__ === Object.prototype // true
經過前面的討論, 從這個代碼可以看出, Function 即是函數也是對象, 並且相當於自己創建了自己, 相當於
Function = new Function();
; Function 的原型對象的構造函數也是 Object, 相當於Function.prototype = new Object()
4. 關系圖
new 的看法, new 出來的對象一定有 _proto_ 指向其構造函數的 prototype.
Function = new Function();
Object = new Function();
Person = new Function();
所有的原型對象 = new Object(); // 非繼承, 人為修改后會發生變化
person = new Person();