手记

JS函数之不要随便bind

JavaScript在ES5中加了个Function.prototype.bind,可以绑定当前对象,于是就不需要再放一个变量来保存this了,在需要使用this的情况下会很方便。

那么Function.prototype.bind到底是怎么实现的呢?原生的实现先不说,Polyfill是我们可以看到的(参考MDN),像这样:

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也是如此。
CoffeeScriptfat 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图个安心的话,可以通通上高逼格的箭头函数。:)



作者:寂寞的原子
链接:https://www.jianshu.com/p/45515682be0d


0人推荐
随时随地看视频
慕课网APP