JavaScript bind函數(shù)手寫教程
經(jīng)常會看到網(wǎng)上各種手寫bind的教程,下面是我在自己實(shí)現(xiàn)手寫bind的過程中遇到的問題與思考。如果對于如何實(shí)現(xiàn)一個手寫bind還有疑惑的話,那么可以先看看上面兩篇文章。
手寫bind vs 原生bind
我們先使用一個典型的手寫bind的例子,代碼如下:
Function.prototype.bind2 = function (context) { if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; var args = Array.prototype.slice.call(arguments, 1); var fNOP = function () {}; var fBound = function () { var bindArgs = Array.prototype.slice.call(arguments); return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs)); } fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }
我們首先用原生bind運(yùn)行一下代碼
function Foo(a) {this.a = a} Foo.prototype.sayHi = function( ) {} let _Foo = Foo.bind(undefined, 'a') new _Foo()
更多面試題解答參見前端手寫面試題詳細(xì)解答
然后使用手寫版代碼,運(yùn)行同樣的代碼
function Foo(a) {this.a = a} Foo.prototype.sayHi = function( ) {} let _Foo = Foo.bind2(undefined, 'a') new _Foo()
我們可以看到相比原生bind方法,手寫版的bind方法返回的構(gòu)造函數(shù),構(gòu)造出來的新對象會比原生的多一層__proto__
。而這個__proto__
產(chǎn)生的原因就是在很多教程中提到的防止原型鏈篡改。
這也就是為什么很多的文章會告訴你,為什么要添加下面的代碼。
var fNOP = function () {}; fNOP.prototype = this.prototype; fBound.prototype = new fNOP();
這段代碼中,使用了一個空函數(shù)作為中轉(zhuǎn),相當(dāng)于Object.create(fBound.prototype)
。具體可以查看文章開頭給出的文章,里面的詳細(xì)的說明。
規(guī)范中的bind
既然說道,加上面的代碼是為了防止原型鏈篡改。我就想看看原生的bind如何處理這個問題的呢?
function Foo(a) {this.a = a} Foo.prototype.sayHi = function( ) {} let _Foo = Foo.bind(undefined, 'a') _Foo.prototype.sayHi = function( ) {console.log('篡改的_Foo的sayHi方法')} (new _Foo().sayHi())
我發(fā)現(xiàn)在運(yùn)行上面的代碼,程序執(zhí)行到修改_Foo
的原型方法的語句時,就已經(jīng)報錯了。提示表明_Foo
沒有prototype
屬性!既然沒有prototype
屬性,那么是不是也就不用處理原型鏈篡改的問題了呢?
之后,我查了一下規(guī)范, 在NOTE中,有下面一段話。明確指出了bind返回的函數(shù)是沒有prototype
屬性,這也多少印證了上面的猜想。
Function objects created using Function.prototype.bind do not have a prototype property or the [[Code]], [[FormalParameters]], and [[Scope]] internal properties.
其中需要注意的有一點(diǎn)是這條:
Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
我自己理解的意思是是bind出來的函數(shù)對象的prototype屬性是內(nèi)建的Function.prototype
屬性, 這里應(yīng)該是說明了為什么原生的bind不會多一層__proto__
屬性
小結(jié)
寫這篇的目的是總結(jié)下自己在實(shí)現(xiàn)bind過程中遇到的問題,記錄探究的過程。通過一系列手寫原生方法,鍛煉了我們對于原理的進(jìn)一步認(rèn)識。但是也要注意驗(yàn)證,實(shí)際去操作幾次,可能得出自己的經(jīng)驗(yàn)。如果有更多的兩者對比的發(fā)現(xiàn),可以在評論里告訴我,歡迎各位大佬斧正。
到此這篇關(guān)于JavaScript bind函數(shù)手寫教程的文章就介紹到這了,更多相關(guān)JS bind函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS組件Bootstrap實(shí)現(xiàn)圖片輪播效果
這篇文章主要為大家詳細(xì)介紹了JS組件Bootstrap實(shí)現(xiàn)圖片輪播效果的具體代碼,對圖片輪播效果感興趣的小伙伴們可以參考一下2016-05-05javascript實(shí)現(xiàn)點(diǎn)擊單選按鈕鏈接轉(zhuǎn)向?qū)?yīng)網(wǎng)址的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)點(diǎn)擊單選按鈕鏈接轉(zhuǎn)向?qū)?yīng)網(wǎng)址的方法,涉及javascript鼠標(biāo)事件及頁面跳轉(zhuǎn)的相關(guān)技巧,簡單實(shí)用,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08詳解Python中l(wèi)ogging日志模塊在多進(jìn)程環(huán)境下的使用
許多應(yīng)用程序中都會有日志模塊,用于記錄系統(tǒng)在運(yùn)行過程中的一些關(guān)鍵信息,以便于對系統(tǒng)的運(yùn)行狀況進(jìn)行跟蹤。這篇文章給大家主要介紹了在Python中l(wèi)ogging日志模塊在多進(jìn)程環(huán)境下的使用,需要的朋友可以參考借鑒,下面來一起看看吧。2016-12-12javascript使用正則控制input輸入框允許輸入的值方法大全
在做項(xiàng)目的時候,我們經(jīng)常會遇到控制input輸入框允許輸入的值為數(shù)字,字母,漢字或者混排的情況,那么我們怎么來處理呢,下面我們就來探討怎么通過用javascript正則來實(shí)現(xiàn)2014-06-06Vuejs通過拖動改變元素寬度實(shí)現(xiàn)自適應(yīng)
這篇文章主要介紹了Vuejs通過拖動改變元素寬度實(shí)現(xiàn)自適應(yīng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09javascript實(shí)現(xiàn)倒計(jì)時并彈窗提示特效
倒計(jì)時的功能在我們做項(xiàng)目的時候會經(jīng)常遇到,這里給大家分享的是個人編寫的一個簡易的效果代碼,有需要的小伙伴可以參考下2015-06-06使用JavaScript實(shí)現(xiàn)貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了使用JavaScript實(shí)現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-09-09