日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bind函数polyfill源码解析

發(fā)布時間:2023/12/2 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bind函数polyfill源码解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

準(zhǔn)備知識

使用new來調(diào)用函數(shù)會自動執(zhí)行下面的操作:

  • 創(chuàng)建一個全新的對象
  • 這個新對象會被執(zhí)行原型連接
  • 這個新對象會綁定到函數(shù)調(diào)用的this
  • 如果函數(shù)沒有返回其他對象,那么new表達(dá)式中的函數(shù)調(diào)用會自動返回這個新對象
  • 注意this綁定規(guī)則,new操作具有最高的優(yōu)先級

    《你不知道的JavaScript(上卷)》提供了一個例子,bar被硬綁定到obj上,但是new bar(3) 并沒有像我們預(yù)計的那樣把obj.a修改為3。相反,new修改了硬綁定調(diào)用bar()中的this。因為使用了new綁定,我們得到了一個名字為baz的新對象,并且baz.a的值為3。

    function foo(something) {this.a = something } var obj = {} var bar = foo.bind(obj) bar(2) console.log(obj.a) //2 var baz = new bar(3) console.log(obj.a) //2 console.log(baz.a) //3

    instanceof運算符的第一個變量是一個對象,暫時稱為A;第二個變量一般是一個函數(shù),暫時稱為B。

    instanceof判斷準(zhǔn)則:沿著A的__proto__這條線來找,同時沿著B的prototype這條線來找,如果兩條線能找到同一個引用,即同一個對象,那么就返回true。

    源碼分析

    MDN上提供的polyfill如下,主要的疑惑點應(yīng)該就是 this instanceof fNOP 作用是什么?

    if (!Function.prototype.bind) {Function.prototype.bind = function(oThis) {if (typeof this !== 'function') {throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable')}var aArgs = Array.prototype.slice.call(arguments, 1),fToBind = this,fNOP = function() {},fBound = function() {return fToBind.apply(this instanceof fNOP // 這段代碼會判斷硬綁定函數(shù)是否是被new調(diào)用,如果是的話就會使用新創(chuàng)建的this替換硬綁定的this? this: oThis,aArgs.concat(Array.prototype.slice.call(arguments)))}// 維護(hù)原型關(guān)系if (this.prototype) {// Function.prototype doesn't have a prototype propertyfNOP.prototype = this.prototype; }fBound.prototype = new fNOP()return fBound} }

    this instanceof fNOP 單獨看是看不明白的,需要結(jié)合以下代碼才能說明它的作用

    if (this.prototype) {fNOP.prototype = this.prototype; } fBound.prototype = new fNOP()

    首先我們要清楚:bind(...)會返回一個硬編碼的新函數(shù),它會把參數(shù)設(shè)置為this的上下文并調(diào)用原始函數(shù)。

    重點就是bind(...)返回的是一個函數(shù)!函數(shù)!函數(shù)!這意味著可以對bind(...)返回的函數(shù)進(jìn)行new操作,那么問題就來了。

    this綁定中new操作具有最高的優(yōu)先級,如果執(zhí)行new操作,bind(...)應(yīng)該不起作用,this應(yīng)該指向new出來的新對象。

    清楚了以上內(nèi)容,我們開始閱讀代碼。

    if (typeof this !== 'function') {throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable')}

    bind(...)必須由函數(shù)調(diào)用,所以以上代碼對this的類型進(jìn)行檢查,如果不是函數(shù)類型則拋出錯誤。

    var aArgs = Array.prototype.slice.call(arguments, 1) var fToBind = this var fBound = function() {return fToBind.apply(this instanceof fNOP // 這段代碼會判斷硬綁定函數(shù)是否是被new調(diào)用,如果是的話就會使用新創(chuàng)建的this替換硬綁定的this? this: oThis,aArgs.concat(Array.prototype.slice.call(arguments)))}

    aArgs獲取傳入的其它參數(shù),fToBind獲取需要硬綁定的函數(shù),fBound為返回的綁定操作函數(shù),我們先忽略fBound里面的內(nèi)容,繼續(xù)往下看。

    if (this.prototype) {fNOP.prototype = this.prototype; } fBound.prototype = new fNOP()

    我們假設(shè)對bind(...)返回的函數(shù)進(jìn)行new操作(原型鏈如下),則this instanceof fNOP 為true,此時我們就知道執(zhí)行了new操作,硬綁定的this不能生效,需要把this綁定到新生成的對象上。

    如果沒有進(jìn)行new操作的話,就用apply模擬bind綁定,一切按照原計劃進(jìn)行。

    最后我們分析一下維護(hù)原型關(guān)系的重要性,例子如下:

    function Foo(){console.log(this.a);this.a=1; } Foo.prototype.show=function() {console.log(this.a)}; Foo(); // undefined var obj1=new Foo(); obj1.show();var bar=Foo.bind({a:2}); bar(); // 2 var obj2=new bar(); obj2.show();

    因為bind函數(shù)內(nèi)部保持了原型關(guān)系的繼承,所以對象obj2才能訪問到原型上的show方法。

    ** 注意:Foo.show()是錯誤的,因為Foo的原型指向的是Function.prototype,只有Foo的實例才能調(diào)用show方法。


    更多專業(yè)前端知識,請上 【猿2048】www.mk2048.com

    總結(jié)

    以上是生活随笔為你收集整理的bind函数polyfill源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。