JavaScript中Function與Object的關(guān)系
原型鏈
我們來回顧一下什么是原型
我們知道js中所有的對象、函數(shù)、數(shù)組都可以看成對象,也就是一切皆是對象
所有的對象身上都有一個(gè)
__proto__屬性,他叫隱式原型,指向了構(gòu)造這個(gè)對象(如obj)的構(gòu)造函數(shù)(例如Constructor)的原型對象即Constructor.prototype,也就是說obj.__proto__===Constructor.prototype,這兩個(gè)指針指向的其實(shí)是同一塊堆空間在構(gòu)造函數(shù)的原型對象prototype(
Constructor.prototype)中,一般包含constructor屬性和__proto__屬性。其中
constructor包含函數(shù)的一些信息如argments、caller、length、name和prototype指向構(gòu)造函數(shù)的原型對象自身以及__scope__即閉包屬性(其中有函數(shù)需要使用的外部變量以及全局上下文,以偽數(shù)組的形式儲存在scope閉包對象中),另外__proto__的話,其實(shí)就是把Constructor.prototype看成new出來的對象實(shí)例,__proto__就是指向Constructor.prototype的構(gòu)造函數(shù)(如Superconstructor)的實(shí)例對象即Superconstructor.prototype具體可以參照下圖:

然后是原型鏈
由于對象(如obj)的隱式原型(
obj.__proto__)指向構(gòu)造函數(shù)的prototype(如Constructor.prototype),而這個(gè)
prototype(如Constructor.prototype)里面又有一個(gè)__proto__,它指向了prototype的構(gòu)造函數(shù)的prototype(如Superconstructor.prototype),然后
Superconstructor.prototype.__proto__指向了Object.prototype這樣就形成了一個(gè)簡單的鏈?zhǔn)浇Y(jié)構(gòu),這個(gè)條鏈的最后是
Object.prototype.__proto__為null
以上就是原型鏈的構(gòu)成
原型鏈的使用
當(dāng)你使用一個(gè)對象的屬性或方法時(shí),會(huì)先在該對象上查找已有屬性,如果沒有,就找到__proto__,找原型身上的屬性,如果原型沒有,那就再找原型的原型身上是否存在待查找屬性,知道找到或者找到原型鏈的頂端null
關(guān)于原型鏈一些有意思的東西
我們知道typeof可以用于判斷變量的數(shù)據(jù)類型,但是對于復(fù)雜數(shù)據(jù)類型,它只能判斷出對象、數(shù)組或函數(shù),這對于我們的使用來說是不夠的
所以我們可以用instanceof來判斷引用數(shù)據(jù)類型的對象類型
typeof A //'function' obj instanceof A //true obj instanceof Object //true
在使用時(shí)我發(fā)現(xiàn)一個(gè)有趣的問題
Function instanceof Object //true Object instanceof Function //true
這是為什么呢?
我們嘗試使用
Function.__proto__===Object.prototype //false
發(fā)現(xiàn)得到的是false,也就是Function并不是Object new出來的
但是嘗試
Object.__proto__===Function.prototype //true
卻發(fā)現(xiàn)Object是由Function new出來的
接著我們分析一下instanceof的工作原理, 我們嘗試用函數(shù)instance_of來手寫instanceof關(guān)鍵字
function instance_of(L, R) {
var O = R.prototype;
L = L.__proto__;
while (true) {
if (L === null)
return false;
if (O === L)
return true;
L = L.__proto__;
}
}對于以上代碼分析,我們其實(shí)是在找左值的原型鏈上是否存在右值的原型
于是我們嘗試
Function.__proto__===Function.prototype //true Function.__proto__.__proto__===Object.prototype //true
發(fā)現(xiàn)原來Function.prototype是由Object new出來的,同時(shí)Function也是可以由自己new出來
- 綜上,
Function由Functionnew出來,Object由Functionnew出來,Function.prototype由Objectnew出來
最后是關(guān)于new關(guān)鍵字
當(dāng)代碼 new Foo(...) 執(zhí)行時(shí),會(huì)發(fā)生以下事情:
- 一個(gè)繼承自
Foo.prototype的新對象被創(chuàng)建(類似于Object.create)。 - 使用指定的參數(shù)調(diào)用構(gòu)造函數(shù)
Foo,并將this綁定到新創(chuàng)建的對象。new Foo不帶括號就是沒有指定參數(shù)列表,Foo不帶任何參數(shù)調(diào)用。 - 由構(gòu)造函數(shù)返回對象,作為
new表達(dá)式的結(jié)果。如果構(gòu)造函數(shù)沒有顯式返回一個(gè)對象,則使用步驟 1 創(chuàng)建的對象。(一般情況下,構(gòu)造函數(shù)不返回值,但是可以選擇主動(dòng)返回對象,來覆蓋正常的對象創(chuàng)建步驟)
嘗試用newFun手寫new關(guān)鍵字
function newFun(Constructor) {
var obj = {};
obj.__proto__ = Constructor.prototype;
return Constructor.apply(obj);
};使用Object.create
function newFun() {
Constructor = [].shift.call(arguments);// 取出第一個(gè)參數(shù)Constructor
var obj = Object.create(Constructor);
return Constructor.apply(obj, arguments);// 使用參數(shù)調(diào)用
};- 補(bǔ)充一點(diǎn)題外話使用對象鏈?zhǔn)秸{(diào)用hh()函數(shù),它的this指向通過隱式綁定還是指向直接調(diào)用它的對象a,而不是間接調(diào)用的對象b
let a = { k:10, hh(){ console.log(this); } } let b = { k:9, a } b.a.hh();
到此這篇關(guān)于JavaScript中Function與Object的關(guān)系的文章就介紹到這了,更多相關(guān)JavaScript Function Object內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js判斷是否為數(shù)組的函數(shù): isArray()
像 Ajaxian,StackOverflow 等,搜一下,到處都在討論 isArray() 的實(shí)現(xiàn)。對于一切都是對象的 JavaScript 來說,確實(shí)有點(diǎn)麻煩2011-10-10
BootStrap 輪播插件(carousel)支持左右手勢滑動(dòng)的方法(三種)
這篇文章主要介紹了BootStrap 輪播插件(carousel)支持左右手勢滑動(dòng)的方法(三種)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
JS實(shí)現(xiàn)獲取進(jìn)今年第幾天是周幾的方法分析
這篇文章主要介紹了JS實(shí)現(xiàn)獲取進(jìn)今年第幾天是周幾的方法,結(jié)合實(shí)例形式對比分析了JavaScript進(jìn)行日期與天數(shù)運(yùn)算相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-06-06
js實(shí)現(xiàn)一個(gè)可以兼容PC端和移動(dòng)端的div拖動(dòng)效果實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)一個(gè)可以兼容PC端和移動(dòng)端的div拖動(dòng)效果實(shí)例,具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12
JavaScript中三個(gè)等號和兩個(gè)等號的區(qū)別(== 和 ===)淺析
javascript中比較運(yùn)算符'=='與'==='可能大家用的比較多,但是大家對他的區(qū)別不是很清楚,接下來小編給大家介紹下js中三個(gè)等號和兩個(gè)等號的區(qū)別(== 和 ===),感興趣的朋友可以參考下2016-09-09
微信小程序開發(fā)(二):頁面跳轉(zhuǎn)并傳參操作示例
這篇文章主要介紹了微信小程序開發(fā)頁面跳轉(zhuǎn)并傳參操作,結(jié)合實(shí)例形式詳細(xì)分析了微信小程序頁面跳轉(zhuǎn)并傳參相關(guān)操作技巧,需要的朋友可以參考下2020-06-06
通過BootStrap實(shí)現(xiàn)輪播圖的實(shí)際應(yīng)用
js我們沒有學(xué)過,今天我是用bootstrap實(shí)現(xiàn)輪播圖的效果,非常不錯(cuò)代碼簡單易懂,需要的朋友參考下吧2016-09-09

