JS函式之不要隨便bind

davidtim發表於2021-09-09

JavaScript在ES5中加了個Function.prototype.bind,可以繫結當前物件,於是就不需要再放一個變數來儲存this了,在需要使用this的情況下會很方便。

那麼Function.prototype.bind到底是怎麼實現的呢?原生的實現先不說,Polyfill是我們可以看到的(參考),像這樣:

if (!Function.prototype.bind) {  Function.prototype.bind = function (oThis) {    if (typeof this !== "function") {      // closest thing possible to the ECMAScript 5 internal IsCallable 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 && oThis
                                 ? this
                                 : oThis || window,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();    return fBound;
  };
}

不難看出,我們得到的其實是一個全新的函式!原函式被封裝起來了,然後在呼叫的時候強制為它指定this
從結果上來看,瀏覽器原生的Function.prototype.bind也是如此。
fat arrow=>)實現的繫結比這個輕量一些,但也是需要將原函式和當前物件存起來,並返回一個新的函式:

func = (a) => doSomething(a)var func = (function(_this) {  return function(a) {    return doSomething(a);
  };
})(this);

那麼為什麼不要濫用呢?
我測試了一下瀏覽器原生的Function.prototype.bind,發現使用了bind之後,函式的記憶體佔用增加了近2倍!CoffeeScript實現的繫結稍微輕量一點,記憶體佔用也增加了1倍多。

再順便測試了下ES6新增的Arrow function(也是=>),因為這個特殊函式是自帶繫結技能的,結果驚奇地發現,它的記憶體佔用和普通的Function沒啥區別。所以以後需要或者不需要bind的場景如果一定要濫用bind圖個安心的話,可以通通上高逼格的箭頭函式。:)



作者:寂寞的原子
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3349/viewspace-2813094/,如需轉載,請註明出處,否則將追究法律責任。

相關文章