JavaScirpt 的 bind 函數究竟作了哪些事

文章原地址javascript


ES5 實現 bind 函數以下java

Function.prototype.bind = function(that){
        var self = this,
            args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
            F = function(){};

        var bound = function(){
            var context = that, length = arguments.length;
            if (this instanceof bound){
                F.prototype = self.prototype;
                context = new F;
            }
            var result = (!args && !length)
                ? self.call(context)
                : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
            return context == that ? result : context;
        };
        return bound;
    }
複製代碼

測試1git

var bar = function() {
        console.log(this.x)
    }
var foo = {
  x: 3
}

var func = bar.bind(foo);
func(); // 3
複製代碼

bar 函數綁定foo 中的x 值,而後輸出3github

bind 函數中最主要的是bound 函數,bound 函數作了哪些事呢?segmentfault

首先context 存儲傳入的thatcontext 中,判斷this instanceof bound ,那何時this instanceof bound == true 呢?在測試1中的案例中,this instanceof boundfalse ,打印此時的this 輸出Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} ,發現是window 對象,由於foo 自己就是在window 對象中。app

因此此時直接執行self.call(context) ,返回執行的結果3 ,就是咱們測試1中的結果。函數

那何時this instanceof bound == true 呢,並且此時還須要使用空函數F 來獲取主函數的prototypepost

答案是實例化,何時實例化呢?測試

測試2ui

var bar = function() {
    console.log(this.x)
}
bar.prototype.name = function(){
  this.name = 'name';
}
var foo = {
  x: 3
}

var func = bar.bind(foo);
var newFunc = new func; // undefined
newFunc.name(); // name
複製代碼

bar.bind(foo) 進行實例化,此時由於進行了new 操做,new 操做作了什麼呢,參考new操做符裏面到底發生了什麼?因此此時的this 爲新生成的bound {} 對象,constructorbound 函數,因此此時this instanceof bound == true

那爲何bar.bind(foo)foo 對象傳遞的時候,沒有輸出3 而是undefined 呢?也是由於new 操做,當前的上下文已是新生成的newFunc 函數了。並且當this instanceof bound == true 時,會把barprototype 賦給F 函數,而bound 函數返回的是new F ,因此這時barprototype 也賦給newFunc 了。

咱們看看ES6的操做,結果和上述例子是同樣的。

var bar = function() {
    console.log(this.x)
}
bar.prototype.name = function(){
    console.log('name')
}
var foo = {
    x: 3
}
var func = bar.bind(foo);
func(); // 3
// 實例化
var newFunc = new func; // undefined
    newFunc.name(); // name
複製代碼

總結:

因此bind 函數總共作了哪幾件事呢?

  • 沒有實例化時,將傳入對象的參數引用到當前函數,執行當前函數,返回結果
  • 實例化時,使用new 操做生成新函數,原函數的prototype 賦給新函數,執行新函數,並返回新函數
相關文章
相關標籤/搜索