Function和Object 應該知道的

javascript有5種基礎的內建對象(Fundamental Objects)ObjectFunctionErrorSymbolBoolean,而Object/Function尤其特殊,是定義其餘內建對象或者普通對象和方法的基礎。javascript

詳細的瞭解ObjectFunction對象有助於更好的理解javascript的一些工做原理。java

和其餘引用類型同樣,Object/Function既是對象,有本身的方法和屬性,也是函數,能夠做爲構造函數。 本文主要討論如下幾個問題:git

  • Fucntion.prototype和普通對象的prototype有何區別?
  • Object.prototype.__proto__ = ?
  • Object.__proto__ = ?
  • ObjectFunction的原型對象有何特殊之處?

Function

Function的屬性

在ES6標準中,Function 對象有兩個屬性:github

  • length 值爲1,這個屬性的特性爲{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true },即不可覆蓋,不可被for...in遍歷,但能夠經過Object.defineProperty修改它的上面這些特性bash

  • prototype 爲原型對象,(見ES最新標準說明 Function.prototpye)它跟通常函數的prototype的區別在於app

    • ❗️它不可寫,不可配置,不可遍歷。 即它永遠指向固定的一個對象,且是其餘全部函數的原型對象,全部函數自己的__proto__指向它。
    const o = {number: 20}
    Function.prototype = o // 依然是原來的值,未改變
    
    
    typeof Array.__proto__ // 'function' [=== Function.prototype]
    typeof Object.__proto__ // 'function' [=== Function.prototype]
    
    typeof Array.prototype.__proto__ // 'object' [=== Object.prototype]
    
    function F () {}
    F.__proto__ === Function.prototype // true
    
    F.prototype = o     // prototype指向o
    複製代碼
    • ❗️它是一個函數。 通常函數的prototype是一個帶有constructor屬性的普通對象,但Functionprototype是一個函數對象(built-in function object),js中惟一一個默認prototype爲函數的對象
    typeof Function.prototype // 'function'
    
    function F () {}
    typeof F.prototype  // ☘ 'object'
    typeof Object.prototype // 'object'
    複製代碼

這是ES標準中規定的Function對象的兩個屬性,但其實在FireFox、Chrome在實現時,還有一個name屬性,它的值就是'Function'。另外還有一個屬性,就是__proto__函數

相比於ObjectFunction對象自帶屬性是比較少的ui

★ Function.prototype

在ES規範,有關Function.prototype部分 定義的Functionprototype的方法有spa

Function.prototype.apply
Function.prototype.bind
Function.prototype.call
Function.prototype.contructor
Function.prototype.toString
Function.prototype[@@hasInstance](V)
複製代碼

函數和對象都有__proto__屬性,指向構造函數的prototype屬性所指向的對象,即它的原型對象。prototype

而函數的__proto__屬性(❗️並不是它的原型對象prototype上的__proto__屬性)指向Function.prototype,因此Function.prototype上的屬性和方法都會被函數對象(function object)所繼承。

經過上面的介紹,相信可以明白如下這些有意思的等式爲什麼成立

Function.__proto__ === Function.prototype // true ❗️
Object.__proto__ === Function.prototype // true
Object.prototype.__proto__ === null // true
Function.prototype.__proto__ === Object.prototype // true
Object.prototype === Object.__proto__ // false
複製代碼

同時,由於函數對象自己有prototype屬性,是Object的實例,因此也繼承了Object.prototype的屬性

Object

★ Object函數對象的屬性

Object做爲函數,與普通函數同樣,有lengthprototype__proto__name屬性,除此以外,還有不少沒有被繼承的私有方法

// 方法
Object.assign()
Object.create()
Object.defineProperties()
Object.defineProperty()
Object.entries()
Object.freeze()
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.getPrototypeOf()
Object.is()
Object.isExtensible()
Object.isFrozen()
Object.isSealed()
Object.keys()
Object.preventExtensions()
Object.seal
Object.setPrototypeOf()
Object.values()
複製代碼

Object函數對象的方法不是這裏的重點,就再也不展開。

★ Object.prototype

Function.prototype和其餘引用類型(Array.prototypeString.prototype)同樣是不可寫不可配置不可for...in遍歷的,但依然能夠被擴展,便可以往Object.prototype新增屬性和方法

Object.isExtensible(Object.prototype) // true
複製代碼
  • ❗️Object.prototype的一個重要特性是,它是全部對象原型鏈的終點,由於Object.prototype.__proto__的值爲null,即
Object.prototype.__proto__ === null
複製代碼

一個對象的實例,沿着它的原型鏈,經過__proto__一層層往上找某一個屬性,若是在Object.prototype上沒找到,那就會返回undefined,因此,原型鏈不會無限的找下去。

function F () {}
F.prototype.age = 20
let f = new F()
f.__proto__ === F.prototype // true
f.__proto__.__proto__ === Object.prototype //true
f.__proto__.proto__.__proto__ === null // true

/** * 查找過程 * f.color -> 沒找到,繼續 * f.__proto__.color(F.prototype) -> 沒找到,繼續 * f.__proto__.__proto__.color(F.prototype.__proto__,Object.prototype) 沒找到,返回undefined * 若是繼續 f.__proto__.__proto__.__proto__ (Object.prototype.__proto__) === null 結果跟上面同樣 */
console.log(f.color) // undefined
複製代碼

Object.prototype上的屬性和方法,會被js中的全部方法和對象所繼承,ES規範中的屬性

Object.prototype.constructor
Object.prototype.hasOwnProperty()
Object.prototype.isPrototypeOf()
Object.prototype.propertyIsEnumerable()
Object.prototype.toLocaleString()
Object.prototype.toString()
Object.prototype.valueOf()
Object.prototype.__proto__
複製代碼

下圖是FunctionObjectFunction.prototypeObject.prototye相互之間關係圖

Function與Object

Object、Function的關係

ObjectFunction之間最讓人琢磨不透的,就是他們的關係

Object instanceof Object // true
Object instanceof Function // true
Function instanceof Function // true
Function instanceof Object // true

const o = {}
o instanceof Object //true
o instanceof Function // false

function F () {}
F instanceof Object //true
F instanceof Function //true
複製代碼

未完待續 ~~~

相關文章
相關標籤/搜索