bind()使用场景及原理

bind()的语法是:

    fun.bind(thisArg[, arg1[, arg2[, ... ]]]);

thisArg:当绑定函数被调用时,该函数会作为原函数运行时的this指向,当使用new操作符调用绑定函数时,该参数无效。

arg1, arg2... :当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

返回值:返回由指定的this值和初始化参数改造的原函数拷贝。

bind()使用场景:

1)作为绑定函数使用,并且设置函数的this值。



````

var name = "The Window";

var object = {

    name : "My Object",

    getNameFunc : function() {

        return function(){

            return this.name;

        }

    }

}

console.log(object.getNameFunc()());//>The Window

````

getNameFunc()返回一个匿名函数,object.getNameFunc()()立即调用它返回的函数,匿名函数的执行环境具有全局性,因此其this对象通常指向window。

为解决上面方法,我们可以把外部作用域中的this对象保存在闭包函数能够访问到的变量里:



````

var name = "The Window";

var object = {

    name : "My Object",

    getNameFunc : function() {

        var _this = this;

        return function(){

            return _this.name;

        }

    }

}

console.log(object.getNameFunc()());//>My Object

````

当然也可以bind()方法:



````

var name = "The Window";

var object = {

    name : "My Object",

    getNameFunc : function() {

        return function(){

            return this.name;

        }.bind(this)

    }

}

console.log(object.getNameFunc()());//>My Object

````

上面通过bind()方法实现的绑定,效果等价于如下:



````

var name = "The Window";

var object = {

name : "My Object",

getNameFunc : function() {

return function(){

return this.name;

}.apply(this)

}

}

console.log(object.getNameFunc());//>My Object

````

2) 偏函数,使一个函数拥有预设的初始值,也称柯里化(currying)



````

var sum = function(x, y) {return x + y;};

var succ = sum.bind(null, 1);//创建一个类似sum的新函数,this值设为null,指向全局变量

//第一个参数绑定到1,新的函数期望只传入一个实参

succ(2);//>3

````

3)配合setTimeout()使用



````

function LateBloomer() {

  this.petalCount = Math.ceil(Math.random() * 12) + 1;

}

// Declare bloom after a delay of 1 second

LateBloomer.prototype.bloom = function() {

//如果不使用bind()绑定作用域,作用域为winidow

  window.setTimeout(this.declare.bind(this), 1000);

};

LateBloomer.prototype.declare = function() {

  console.log('I am a beautiful flower with ' +

    this.petalCount + ' petals!');

};

var flower = new LateBloomer();

flower.bloom();  

````

4) 作为构造函数的绑定函数,即通过new关键字调用bind()产生的绑定函数,bind()中俄第一个参数(指定this值的参数)不起作用,后续参数正常使用。



````

function Person(_age, _address) {

this.age = _age;

this.address = _address;

console.log(this.name);//undefined

console.log(this.age);//23

}

var north = {

name : "north"

}

var northBind = Person.bind(north, 24);

var northObj = new northBind();

````

name并不是north对象含有的名字,可见第一个参数并没有起作用。

bind()的原理是:



````

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

                ? this

                : oThis,

                 // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的

                aArgs.concat(Array.prototype.slice.call(arguments)));

        };

   // 维护原型关系

    if (this.prototype) {

      // Function.prototype doesn't have a prototype property

      fNOP.prototype = this.prototype;

    }

    fBound.prototype = new fNOP();

    return fBound;

  };

}

````

看这段代码需要注意的的几个点:

1. bind()返回值是改造参数后的原函数的拷贝,所以调用bind()的必须是函数;

2. 如果返回的函数是一个构造函数,那么this不改变,即不会被传入的第一反应参数重写。

3. fBound函数中对arguments的操作,其实是对bind()函数返回的绑定函数的参数的操作,aArgs和arguments的合并实现了参数预设功能。

4. bind()函数返回的绑定函数与最开始的原函数具有相同的原型

bind()和apply()、call()的区别:

bind()返回一个绑定函数,apply()、call()是立即调用原函数。

备注:可能还是没有完全理解bind吧。。。

参考:

Function.prototype.bind()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 6,628评论 1 10
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 6,261评论 0 2
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 12,422评论 2 17
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 9,776评论 0 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,281评论 19 139

友情链接更多精彩内容