object htmldivelement什么意思_深入探究 Function amp; Object 鸡蛋问题
(給前端樹加星標,提升前端技能)
轉自:高級前端進階引言
上篇文章用圖解的方式向大家介紹了原型鏈及其繼承方案,在介紹原型鏈繼承的過程中講解原型鏈運作機制以及屬性遮蔽等知識,今天這篇文章就來深入探究下 Function.__proto__ === Function.prototype 引起的雞生蛋蛋生雞問題,并在這個過程中深入了解 Object.prototype、Function.prototype、function Object 、function Function 之間的關系。
Object.prototype
我們先來看看 ECMAScript 上的定義(15.2.4)。
The value of the [[Prototype]] internal property of the Object prototype object is null, the value of the [[Class]] internal property is "Object", and the initial value of the [[Extensible]] internal property is true.Object.prototype 表示 Object 的原型對象,其 [[Prototype]] 屬性是 null,訪問器屬性 __proto__ 暴露了一個對象的內部 [[Prototype]] 。 Object.prototype 并不是通過 Object 函數創建的,為什么呢?看如下代碼
function Foo() {this.value = 'foo'; } let f = new Foo(); f.__proto__ === Foo.prototype; // true實例對象的 __proto__ 指向構造函數的 prototype,即 f.__proto__ 指向 Foo.prototype,但是 Object.prototype.__proto__ 是 null,所以 Object.prototype 并不是通過 Object 函數創建的,那它如何生成的?其實 Object.prototype 是瀏覽器底層根據 ECMAScript 規范創造的一個對象。
Object.prototype 就是原型鏈的頂端(不考慮 null 的情況下),所有對象繼承了它的 toString 等方法和屬性。
Function.prototype
我們先來看看 ECMAScript 上的定義(15.3.4)。
The Function prototype object is itself a Function object (its [[Class]] is "Function").The value of the [[Prototype]] internal property of the Function prototype object is the standard built-in Object prototype object.
The Function prototype object does not have a valueOf property of its own; however, it inherits the valueOf property from the Object prototype Object.
Function.prototype 對象是一個函數(對象),其 [[Prototype]] 內部屬性值指向內建對象 Object.prototype。Function.prototype 對象自身沒有 valueOf 屬性,其從 Object.prototype 對象繼承了valueOf 屬性。
Function.prototype 的 [[Class]] 屬性是 Function,所以這是一個函數,但又不大一樣。為什么這么說呢?因為我們知道只有函數才有 prototype 屬性,但并不是所有函數都有這個屬性,因為 Function.prototype 這個函數就沒有。
Function.prototype // ? () { [native code] }Function.prototype.prototype // undefined當然你會發現下面這個函數也沒有 prototype 屬性。
let fun = Function.prototype.bind() // ? () { [native code] }fun.prototype // undefined為什么沒有呢,我的理解是 Function.prototype 是引擎創建出來的函數,引擎認為不需要給這個函數對象添加 prototype 屬性,不然 Function.prototype.prototype… 將無休無止并且沒有存在的意義。
function Object
我們先來看看 ECMAScript 上的定義(15.2.3)。
The value of the [[Prototype]] internal property of the Object constructor is the standard built-in Function prototype object.Object 作為構造函數時,其 [[Prototype]] 內部屬性值指向 Function.prototype,即
Object.__proto__ === Function.prototype // true使用 new Object() 創建新對象時,這個新對象的 [[Prototype]] 內部屬性指向構造函數的 prototype 屬性,對應上圖就是 Object.prototype。
當然也可以通過對象字面量等方式創建對象。
- 使用對象字面量創建的對象,其 [[Prototype]] 值是 Object.prototype。
- 使用數組字面量創建的對象,其 [[Prototype]] 值是 Array.prototype。
- 使用 function f(){} 函數創建的對象,其 [[Prototype]] 值是 Function.prototype。
- 使用 new fun() 創建的對象,其中 fun 是由 JavaScript 提供的內建構造器函數之一(Object, Function, Array, Boolean, Date, Number, String 等等),其 [[Prototype]] 值是 fun.prototype。
- 使用其他 JavaScript 構造器函數創建的對象,其 [[Prototype]] 值就是該構造器函數的 prototype 屬性。
function Function
我們先來看看 ECMAScript 上的定義(15.3.3)。
The Function constructor is itself a Function object and its [[Class]] is "Function". The value of the [[Prototype]] internal property of the Function constructor is the standard built-in Function prototype object.Function 構造函數是一個函數對象,其 [[Class]] 屬性是 Function。Function 的 [[Prototype]] 屬性指向了 Function.prototype,即
Function.__proto__ === Function.prototype // true到這里就有意思了,我們看下雞生蛋蛋生雞問題。
Function & Object 雞蛋問題
我們看下面這段代碼
Object instanceof Function // true Function instanceof Object // trueObject instanceof Object // true Function instanceof Function // trueObject 構造函數繼承了 Function.prototype,同時 Function 構造函數繼承了Object.prototype。這里就產生了 雞和蛋 的問題。為什么會出現這種問題,因為 Function.prototype 和 Function.__proto__ 都指向 Function.prototype。
// Object instanceof Function 即 Object.__proto__ === Function.prototype // true// Function instanceof Object 即 Function.__proto__.__proto__ === Object.prototype // true// Object instanceof Object 即 Object.__proto__.__proto__ === Object.prototype // true// Function instanceof Function 即 Function.__proto__ === Function.prototype // true對于 Function.__proto__ === Function.prototype 這一現象有 2 種解釋,爭論點在于 Function 對象是不是由 Function 構造函數創建的一個實例?
解釋 1、YES:按照 JavaScript 中“實例”的定義,a 是 b 的實例即 a instanceof b 為 true,默認判斷條件就是 b.prototype 在 a 的原型鏈上。而 Function instanceof Function 為 true,本質上即 Object.getPrototypeOf(Function) === Function.prototype,正符合此定義。
解釋 2、NO:Function 是 built-in 的對象,也就是并不存在“Function對象由Function構造函數創建”這樣顯然會造成雞生蛋蛋生雞的問題。實際上,當你直接寫一個函數時(如 function f() {} 或 x => x),也不存在調用 Function 構造器,只有在顯式調用 Function 構造器時(如 new Function('x', 'return x') )才有。
我個人偏向于第二種解釋,即先有 Function.prototype 然后有的 function Function() ,所以就不存在雞生蛋蛋生雞問題了,把 Function.__proto__ 指向 Function.prototype 是為了保證原型鏈的完整,讓 Function 可以獲取定義在 Object.prototype 上的方法。
最后給一個完整的圖,看懂這張圖原型就沒問題了。
內置類型構建過程
JavaScript 內置類型是瀏覽器內核自帶的,瀏覽器底層對 JavaScript 的實現基于 C/C++,那么瀏覽器在初始化 JavaScript 環境時都發生了什么?
沒找到官方文檔,下文參考自 https://segmentfault.com/a/1190000005754797。對于其觀點比較認同,歡迎小伙伴提出不同觀點。1、用 C/C++ 構造內部數據結構創建一個 OP 即 (Object.prototype) 以及初始化其內部屬性但不包括行為。
2、用 C/C++ 構造內部數據結構創建一個 FP 即 (Function.prototype) 以及初始化其內部屬性但不包括行為。
3、將 FP 的 [[Prototype]] 指向 OP。
4、用 C/C++ 構造內部數據結構創建各種內置引用類型。
5、將各內置引用類型的[[Prototype]]指向 FP。
6、將 Function 的 prototype 指向 FP。
7、將 Object 的 prototype 指向 OP。
8、用 Function 實例化出 OP,FP,以及 Object 的行為并掛載。
9、用 Object 實例化出除 Object 以及 Function 的其他內置引用類型的 prototype 屬性對象。
10、用 Function 實例化出除Object 以及 Function 的其他內置引用類型的 prototype 屬性對象的行為并掛載。
11、實例化內置對象 Math 以及 Grobal
至此,所有內置類型構建完成。
參考
從探究Function.__proto__===Function.prototype過程中的一些收獲高能!typeof Function.prototype 引發的先有 Function 還是先有 Object 的探討
從__proto__和prototype來深入理解JS對象和原型鏈
覺得本文對你有幫助?請分享給更多人
關注「前端樹」加星標,提升前端技能
喜歡就點一下「在看」唄~
總結
以上是生活随笔為你收集整理的object htmldivelement什么意思_深入探究 Function amp; Object 鸡蛋问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql_install_db is
- 下一篇: sklearn朴素贝叶斯分类器_pyth