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

本文按以下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. 多并发编程基础 之线程程 Thried

    原贴 https://www.cnblogs.com/gbq-dog/p/10365669.html 今日要整理的内容有 1. 操作系统中线程理论 2.python中的GIL锁 3.线程在python ...

  2. Asp.net的生命周期之应用程序生命周期

    参考:http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx 参考:http://www.cnblogs.com/JimmyZh ...

  3. Keil软件编程问题归总

    Q:KEIL.uVision.RealView.MDK.KEIL C51之间的关系纠葛(比较区别)? A: KEIL是公司的名称,有时候也指KEIL公司的所有软件开发工具,目前2005年Keil由AR ...

  4. springmvc常遇到的错误

    错误1: HTTP Status 500 - Handler processing failed; nested exception is java.lang.NoClassDefFoundError ...

  5. Welcome! This is the documentation for Python 3.6.8

    The Zen of Python, by Tim Peters Beautiful is better than ugly.Explicit is better than implicit.Simp ...

  6. Scrapyd API的安装

    安装好了Scrapyd之后,我们可以直接请求它提供的API来获取当前主机的Scrapy任务运行状况.比如,某台主机的IP为192.168.1.1,则可以直接运行如下命令获取当前主机的所有Scrapy项 ...

  7. C# GDI+开发手记

    创建画布画字体文字区域内居中换行文字在整个画布中居中画直线画圆形头像压缩保存图片缩放旋转单位换算 创建画布 Bitmap image = new Bitmap(640, 1136, PixelForm ...

  8. Mac OS 10.12使用U盘重装(转)

    OS X Capitan和macOS Sierra的安装方式和下载系统的方法都是一致的,下面是OS X Capitan的安装方法: 一.准备工作: 准备一个8GB或者8G以上容量的U盘 确保里面的数据 ...

  9. spring boot快速入门 1 :创建项目、 三种启动项目方式

    准备工作: (转载)IDEA新建项目时,没有Spring Initializr选项 最近开始使用IDEA作为开发工具,然后也是打算开始学习使用spring boot. 看着博客来进行操作上手sprin ...

  10. Elastic-Job源码分析之JobScheduler类分析

    JobScheduler这个类是EJ中比较核心的一个类,我们现在开始解析这个类. 一.构造器 首先我们看一下JobScheduler的几个构造器. private JobScheduler(final ...