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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bind的那些事

發布時間:2025/6/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bind的那些事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近面頭條的時候,要求自己手動實現一個bind函數,然后又問了bind還能干嘛。這里就圍繞這兩個好好寫一下。

首先bind的文檔說明: (鏈接:傳送門 )

bind()方法創建一個新的函數, 當被調用時,將其this關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。
fun.bind(thisArg[, arg1[, arg2[, ...]]])
參數

  • thisArg
    當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。當使用new 操作符調用綁定函數時,該參數無效。
  • arg1, arg2, ...
    當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。
  • 返回值
    返回由指定的this值和初始化參數改造的原函數拷貝

bind() 函數會創建(返回)一個新函數(稱為綁定函數),新函數與被調函數(綁定函數的目標函數)具有相同的函數體(在 ECMAScript 5 規范中內置的call屬性)。當新函數被調用時 this 值綁定到 bind() 的第一個參數,該參數不能被重寫。綁定函數被調用時,bind() 也接受預設的參數提供給原函數。(注意這句話是重點,也就是說bind支持了這個功能)

一般新手分不清于call,apply的關系,call/apply一般會伴隨這函數的調用的,而bind只是返回了帶新this的函數,將在下次調用。一般用法是調用bind后賦給一個變量,支持調用的時候繼續傳參。

我們一般快速實現一個bind:

/*函數體內的this,就是需要綁定this的實例函數,或者說是原函數。最后我們使用apply來進行參數(context)綁定,并返回。 同時,將第一個參數(context)以外的其他參數,作為提供給原函數的預設參數,這也是基本的柯里化基礎。(應該是偏函數)*/ Function.prototype.bind = Function.prototype.bind || function(context) {var self = this;arg = Array.prototype.slice.call(arguments,1);return function() {return self.apply(context,arr);} }

但是這個實現有個問題,我們將參數限定了arguments.slice(1),我們返回的綁定函數中,如果想實現預設傳參,上個代碼就不能滿足了。
eg:

function sum(a, b) {console.log(a + b) }var sum2 = sum.bind(null,2); // 固定參數a, 值為2 sum2(4) // 傳入參數b, 值為4, 結果為6 重在我們在調用函數的時候可以預設傳參

那么我們將上個bind的實現更完善一下:

Function.prototype.bind = Function.prototype.bind || function(context) {var self = this;var args = Array.prototype.slice.call(arguments,1);return function() {var innerArgs = Array.prototype.slice.call(arguments);var FinalArgs = args.concat(innerArgs);return self.apply(context,FinalArgs);} }

這樣就是實現了偏函數功能,在一些資料里是說“柯里化”,我覺得還是有點區別的,共同特點是實現了參數復用。

關于柯里化和偏函數舉個小例子就知道了:
假設有一個Add(x,y,z)函數,接收x,y,z三個參數,返回x+y+z

  • 偏函數

AddBySeven =Otherbind(Add, 7);
AddBySeven(5, 10); // returns 22;
這是偏函數,固定了你函數的某一個或幾個參數,返回一個新的函數,接收剩下的參數, 參數個數可能是1個,也可能是2個,甚至更多。

  • 柯里化:把一個有n個參數的函數變成n個只有1個參數的函數

curryAdd = Curry(Add);
AddBySeven = curryAdd(7);
AddBySeven(5)(10); // returns 22
// curryAdd(7)(5)(10)

Add = (x, y, z) => x + y + z
變成了CurryAdd = x => y => z => x + y + z

很多資料有的叫柯里化有的叫偏函數,這點我覺得還是讀者自己判斷把。

到這里可能大家覺得上面的實現已經完美了,但是JS的坑是補不完的,問題又來了!
看過文檔的就知道,在文檔上介紹bind時還說了這點:

一個綁定函數也能使用new操作符創建對象:這種行為就像把原函數當成構造器。提供的 this 值被忽略,同時調用時的參數被提供給模擬函數。

那么如果bind返回的函數當做構造函數調用的時候,我們就需要在內部重新構造原型鏈了。所以更兼容的寫法來了:

Function.prototype.bind = Function.prototype.bind || function(context) {if(typeof this !== 'function') {throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');}var self = this;var args = Array.prototype.slice.call(arguments,1);var Fun = {};Fun.prototype = this.prototype;//繼承原來函數var Comb = function(){var innerArgs = Array.prototype.slice.call(arguments);var FinalArgs = args.concat(innerArgs);return self.apply(this instanceof Fun ? this : context || this ,FinalArgs);}Comb.prototype = new Fun();return Comb;}

這里的點:

  • 第一個this是第一次調用bind的函數,也必須是函數,所以在之前就做了一個容錯判斷。

  • 如果最后我們是以new 調用bind返回的函數,即當做構造函數調用,那么這里的this就是Comb的實例,這時候因為Fun繼承了之前調用的函數,Comb又new了Fun,Comb即是Fun的派生類,因此 this instanceof fNOP === true,這時候無視 bind 效果,因此 this 該是什么還是什么。模仿了原本bind的feature,如果這個條件判斷失敗,則使用context 去替換 this。如果context沒傳,那么this該是什么就是什么。

  • 但這里再想想面試官當時的的問題,"bind還能干嘛",其實這個bind就是改變上下文還能干嘛,其實面試管的意思是利用bind的這個feature可以干嘛

    把bind本身的作用講講,在把上面bind本身的偏函數功能(允許第一次傳參不完全,后面調用可以繼續傳參),自己實現的偏函數,作為new 構造函數來調用這些講講,就夠了。

    最后再加一個bind的小功能把,平常我們轉換偽數組,通常是使用:

    var slice = Array.prototype.slice;// ...slice.call(arguments);//arguments是一個偽數組

    如果我們用bind把對象參數綁定到call上返回給slice,每次就不用調用call了,而且還不影響原函數的this:

    var combSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(combSlice);// ...slice(arguments);//slice是一個新函數

    好了,bind的這些事到此結束,歡迎在下方交流評論。

    轉載于:https://www.cnblogs.com/zhangmingzhao/p/8660985.html

    總結

    以上是生活随笔為你收集整理的bind的那些事的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。