前言:之前一直不懂这个函数是干嘛的,最近慢慢有点懂了,说一说自己的理解~

本文按以下3个方面来谈谈bind函数

1)对bind函数的理解;

2)如何使用bind函数

3)自定义bind函数

https://msdn.microsoft.com/zh-cn/library/ff841995中有bind函数较详细的说明)

bind函数的理解

语法:

function.bind(thisArg[,arg1[,arg2[,argN]]])

首先不看传的参数,bind函数实现的功能就是将function绑定在thisArg环境上,使其可以在thisArg上调用function。听起来这和apply/call的作用好像一样,那到底是不是一样呢?

var a={x:1};
function foo(){
return this.x;
}
console.log(foo.call(a));//1
console.log(foo.bind(a));//function foo(){return this.x;}

观察以上代码发现,call函数实现了在a对象上调用foo函数,但bind函数却返回了foo的主体。那这不是没起任何作用?

var a={x:1};
function foo(){
return this.x;
}
var foo_bind = foo.bind(a);
console.log(foo);//function foo(){return this.x;}
console.log(foo_bind);//function foo(){return this.x;}
console.log(foo());//undefined
console.log(foo_bind());//1

通过以上代码可以发现,虽然通过bind绑定后返回的是foo函数主体,但是有差别的:通过bind绑定后返回的函数运行时已经是在a的环境中运行了(而单独运行foo是在window中,所以this.x返回undefined)。

综上可以总结为:bind函数实现与call/apply相似的功能:将给定函数绑定到特定的this环境中;但是bind函数绑定不是立刻执行,只是实现绑定,等到需要执行的时候再执行,此时才完成了和call/apply一样的功能。

那bind函数的这个作用又什么用呢?它一般用在回调函数和事件处理程序中(也就是异步编程中),举个例子

//bind方法
btn.onclick = foo.bind(a);
//匿名函数方法
btn.onclick = function(){
foo.call(a);
}

以上两种方法实现相同的功能,再举个例子

//bind方法
setTimeout(foo.bind(a), 1000);
//匿名函数方法
setTimeout(function() { foo.call(a); }, 1000);

通过以上两个例子可以很清楚的看出,call函数相当于把绑定和执行一次性完成了(匿名函数达到了将其分开的作用),bind函数就是将绑定与执行分开了。

如何使用bind函数

上一部分其实已经讲了怎么使用,这一部分主要是将带参数是怎么使用。

规则:绑定函数将bind中指定的参数作为优先参数,在调用绑定函数时指定的参数作为辅助参数。啥意思?

var a={};
function foo(a,b,c){
alert( a+b+c);
}
var foo_bind = foo.bind(a,"A","B")
foo_bind("X","Y","Z");//"ABX"
var foo_bind2 = foo.bind(a,"A","B","C")
foo_bind2("X","Y","Z");//"ABC"

观察以上代码,发现“A”,"B”作为优先参数转给了函数foo,而调用时传入的"X","Y","Z"要接在"A","B"后面(如果还需要就传,不需要了就不传了)

自定义bind函数

通过第一部分的讲解,其实自定义bind就很简单了。

首先,先不考虑传参数,写出简单的自定义bind

var a={x:1};
function foo(a,b,c){
alert (a+b+c+this.x);
}
function bind(fn,context){
return function(){
return fn.apply(context,arguments);
}
}
var foo_bind=bind(foo,a);
foo_bind("A","B","C");//"ABC1"

可以看出,其实就是用一个闭包把apply/call函数包起来了(即第一部分中讲到的),这里用apply是为了方便用arguments传参。注意,这里的arguments是指调用时的参数,而不是bind函数的。

接下来考虑给bind函数传参数。

var a={x:1};
function foo(a,b,c){
alert (a+b+c+this.x);
}
function bind(fn,context){
//从第3个参数开始取
var args1 = Array.prototype.slice.call(arguments,2);
return function(){
//将bind函数的参数args1与调用时的参数arguments按先后顺序排列
var args2= args1.concat(Array.prototype.slice.call(arguments));
return fn.apply(context,args2);
}
}
var foo_bind=bind(foo,a,"a");
foo_bind("A","B","C");//"aAB1"

到这里,就算都讲完了。这是我自己的理解,希望可以帮到你~

参考资料:

1)https://msdn.microsoft.com/zh-cn/library/ff841995

2)《JavaScript高级程序设计(第3版)》第602-604页。

理解bind函数的更多相关文章

  1. 理解Underscore中的_.bind函数

    最近一直忙于实习以及毕业设计的事情,所以上周阅读源码之后本周就一直没有进展.今天在写完开题报告之后又抽空看了一眼Underscore源码,发现上次没有看明白的一个函数忽然就豁然开朗了,于是赶紧写下了这 ...

  2. bind()函数的深入理解及两种兼容方法分析

    在JavaScript中,bind()函数仅在IE9+.Firefox4+.Chrome.Safari5.1+可得到原生支持.本文将深入探讨bind()函数并对两种兼容方法进行分析比较.由于本文将反复 ...

  3. 理解并手写 bind() 函数

    有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...

  4. 深入理解javascript函数系列第三篇——属性和方法

    × 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...

  5. call,apply,bind函数

    一.call函数 a.call(b); 简单的理解:把a对象的方法应用到b对象上(a里如果有this,会指向b) call()的用法:用在函数上面 var Dog=function(){ this.n ...

  6. C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数

    一.lambda表达式 lambda表达式原型: [capture list] (parameter list) -> retrue type { function body } 一个lambd ...

  7. Javascript中的bind()函数

    今天看到公司大神的一段代码: function ReplaceProcessor() { this._dom = { btnReplace: $('#ro_btnReplace'), btnCompl ...

  8. 关于原生js中bind函数的实现

    今天继续研究了bind函数的实现,也知道了shim和polyfill的说法,现在总结一下, if (!Function.prototype.bind) { Function.prototype.bin ...

  9. 函数式编程之-bind函数

    Bind函数 Bind函数在函数式编程中是如此重要,以至于函数式编程语言会为bind函数设计语法糖.另一个角度Bind函数非常难以理解,几乎很少有人能通过简单的描述说明白bind函数的由来及原理. 这 ...

随机推荐

  1. Laravel 完整开源项目大全

    来自 Laravel学院:http://laravelacademy.org/ http://laravelacademy.org/laravel-project 原型项目 Laravel 5 Boi ...

  2. 通过API方式查看Azure Sign-ins记录

    经确认,目前Sign-ins功能在中国区还没有开通.也没有相关的预计开通时间.您可以通过如下链接随时关注China Azure的最新公告:https://www.azure.cn/zh-cn/what ...

  3. Linux之E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它?

    解决 ubantu系统中 E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它? 的 问题. 1.解决办法: 当我们有的时候在使用apt-get install/update ...

  4. js 弹性导航

    <style> *{margin:0;padding:0;} #box{height:50px;float:left;position:relative;background:#f90;} ...

  5. MONO MessageBox 类

    MessageBox类,负责提示各种消息.   using System; using Android.App; using Android.Content; namespace Box { publ ...

  6. (转)mysql、innodb和加锁分析

    mysql.innodb和加锁分析 原文:https://liuzhengyang.github.io/2016/09/25/mysqlinnodb/ 介绍 本文主要介绍MySQL和InnoDB存储引 ...

  7. Linux网络编程服务器模型选择之并发服务器(下)

    前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接, ...

  8. sysv-rc-conf介绍

    sysv-rc-conf简介 sysv-rc-conf是一个强大的服务管理程序,Ubuntu运行级别Linux 系统任何时候都运行在一个指定的运行级上,不同的运行级的程序和服务都不同,所要完成的工作和 ...

  9. Cloudera Manager安装之Cloudera Manager 5.3.X安装(三)(tar方式、rpm方式和yum方式)

    不多说,直接上干货! 福利每天都有  =>  =>=>=>=> 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师  ...

  10. Tomcat *的安装和运行(绿色版和安装版都适用)

    不多说,直接上干货! 前提, Tomcat *的下载(绿色版和安装版都适用) 一.Tomcat的安装版 1.新建安装目录 2.放置安装版的tomcat 3.双击 4.点击 I agree 5.选择“F ...