JS function 是函式也是物件, 淺談原型鏈
阿新 • • 發佈:2021-01-02
# JS function 是函式也是物件, 淺談原型鏈
> JS 唯一支援的繼承方式是通過原型鏈繼承, 理解好原型鏈非常重要, 我記錄下我的理解
### 1. 前言
1. new 出來的例項有 \__proto__ 屬性, 並且指向其建構函式的 prototype 物件
```js
function Person(){}
const person = new Person();
person.__proto__ === Person.prototype // true
```
2. 所有 new 出來的例項有 \__proto__ 屬性, 所有函式有 prototype 屬性
3. 不要小看任何一個物件, 這個物件有可能是一個函式; 不要小看任何一個函式, 這個函式有可能也是一個物件
4. 只要是物件, 一定就有相應的建構函式 ( 除了 Object 的原型物件找不到 )
### 2. 有趣的部分 1. function 是函式, 但也是物件 2. Object 是函式, 但也是物件 3. 看一個物件是不是函式, 就看它有沒有 prototype 屬性, 像原型物件沒有, 它就只是單純的物件, 不是函式 ( 原型物件無原型 ) 4. Function 是函式, 也是物件, 並且它作為物件的 \__proto__ 屬性 等於 它作為函式的 prototype 屬性, 這說明, 它 **自己建立自己**
### 3. 解釋 1. 以這個為例 ```js function Person(){} const person = new Person(); ```
2. function 是函式, 但也是物件 - 是函式 ```js Person.prototype // {constructor: ƒ ...} Person.prototype.constructor === Person // true ``` 這說明 Person 是函式, 有原型, 原型的 constructor 指向自己 - 是物件 ```js Person.__proto__ // ƒ () { [native code] } Person.__proto__ === Function.prototype //true ``` 這說明 Person 是物件, 相當於 `Person = new Function() `, 有沒有那味了呢
3. 原型物件是單純的物件, 不是函式 ```js Person.prototype.prototype // undefined 不是函式, 無原型 Person.prototype.__proto__ // {constructor: ƒ...} Person.prototype.__proto__ === Object.prototype // true ``` 原型物件無原型, 說明原型物件就只是一個物件, 是物件肯定就有建構函式, 其建構函式是 Object, 相當於 `Person.prototype = new Object()`
4. Object 是函式, 但也是物件 ```js Object.prototype // {constructor: ƒ ...} 是函式, 有原型 Object.prototype.__proto__ // null 所有物件都有其建構函式, Object 原型物件例外 Object.__proto__ // ƒ () { [native code] } Object 是物件 Object.__proto__ === Function.prototype // true ``` Object 有原型物件, 說明它是個函式, 並且它的原型是唯一一個找不到建構函式的; Object 是物件, 有自己的建構函式, 並且它的建構函式是 Function. 相當於 `Object = new Function()`
5. Function 是函式, 也是物件, 並且它自己建立自己 ```js 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. 關係圖 ![繼承關係](http://cdn.xiaxiang.tech/image/blogs/html/JavaScript/繼承關係/繼承關係.png) new 的看法, new 出來的物件一定有 \__proto__ 指向其建構函式的 prototype. ```js Function = new Function(); Object = new Function(); Person = new Function(); 所有的原型物件 = new Object(); // 非繼承, 人為修改後會發生變化 person = new Person
### 2. 有趣的部分 1. function 是函式, 但也是物件 2. Object 是函式, 但也是物件 3. 看一個物件是不是函式, 就看它有沒有 prototype 屬性, 像原型物件沒有, 它就只是單純的物件, 不是函式 ( 原型物件無原型 ) 4. Function 是函式, 也是物件, 並且它作為物件的 \__proto__ 屬性 等於 它作為函式的 prototype 屬性, 這說明, 它 **自己建立自己**
### 3. 解釋 1. 以這個為例 ```js function Person(){} const person = new Person(); ```
2. function 是函式, 但也是物件 - 是函式 ```js Person.prototype // {constructor: ƒ ...} Person.prototype.constructor === Person // true ``` 這說明 Person 是函式, 有原型, 原型的 constructor 指向自己 - 是物件 ```js Person.__proto__ // ƒ () { [native code] } Person.__proto__ === Function.prototype //true ``` 這說明 Person 是物件, 相當於 `Person = new Function() `, 有沒有那味了呢
3. 原型物件是單純的物件, 不是函式 ```js Person.prototype.prototype // undefined 不是函式, 無原型 Person.prototype.__proto__ // {constructor: ƒ...} Person.prototype.__proto__ === Object.prototype // true ``` 原型物件無原型, 說明原型物件就只是一個物件, 是物件肯定就有建構函式, 其建構函式是 Object, 相當於 `Person.prototype = new Object()`
4. Object 是函式, 但也是物件 ```js Object.prototype // {constructor: ƒ ...} 是函式, 有原型 Object.prototype.__proto__ // null 所有物件都有其建構函式, Object 原型物件例外 Object.__proto__ // ƒ () { [native code] } Object 是物件 Object.__proto__ === Function.prototype // true ``` Object 有原型物件, 說明它是個函式, 並且它的原型是唯一一個找不到建構函式的; Object 是物件, 有自己的建構函式, 並且它的建構函式是 Function. 相當於 `Object = new Function()`
5. Function 是函式, 也是物件, 並且它自己建立自己 ```js 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. 關係圖 ![繼承關係](http://cdn.xiaxiang.tech/image/blogs/html/JavaScript/繼承關係/繼承關係.png) new 的看法, new 出來的物件一定有 \__proto__ 指向其建構函式的 prototype. ```js Function = new Function(); Object = new Function(); Person = new Function(); 所有的原型物件 = new Object(); // 非繼承, 人為修改後會發生變化 person = new Person