Javascript中的bind()函数
今天看到公司大神的一段代码:
function ReplaceProcessor() {
this._dom = {
btnReplace: $('#ro_btnReplace'),
btnComplete: $('#ro_btnComplete')
};
// Bind events
this._dom.btnReplace.on('click', this._onReplace.bind(this));
this._dom.btnComplete.on('click', this._onComplete.bind(this));
} ReplaceProcessor.prototype._onReplace = function() {
// code
this._dom.btnComplete.html("OK");
}
这里面最后两行代码是向DOM节点上绑定事件,"this._onReplace.bind(this)"明显就是绑定的执行函数,在不知道具体作用的情况下猜测一下bind()的作用可能和call或者apply类似,用来改变function执行时的上下文环境,不知道理解的对不对所以找资料来印证一下。
先上官网的解释,不管我们个人的解释是多么的接地气,官方API到底还是比较靠谱的:
bind方法会创建一个新函数,称为绑定函数.当调用这个绑定函数时,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.
这个解释多读几次还是很靠谱的,不是很难懂。从功能描述上看和call以及apply还是有区别的,应用的场景不太一样,bind主要是为了改变函数内部的this指向,这个是在ECMA5以后加入的,所以IE8一下的浏览器不支持,当然有兼容的办法,不过坦白说首先对于IE8以下实在无爱,其次那种情况下估计你也没什么心情用bind了吧。。。
东西就是这么个东西,最主要的还是应用的场景,什么情况下使用。本文一开始代码中使用.bind(this)的效果就相当于将事件绑定的callback抽出来写,但是同时还维持了函数中的this指向。本来事件绑定的处理函数一般是一个匿名函数,这里相当于单独抽出来从而使结构更清晰的同时,this指向的是ReplaceProcessor的实例。
这里列举三部分的代码来说明bind能为我们做些什么,同时它的好处在哪里。
(一)事件处理函数
所谓的事件处理函数其实就是绑定事件后的那个callback,这里如果用上bind你的代码应该会简洁优雅一些,我在开篇列出的那段代码里就是这样做的。
var logger = {
x: 0,
updateCount: function() {
this.x++;
console.log(this.x);
}
}
// 下面两段代码的实现是一样的
document.querySelector('button').addEventListener('click', function() {
logger.updateCount();
});
document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));
如何,这就是我之前说的,本来通常情况下处理函数都要用一层匿名函数包裹一下,才能维持处理函数本身的this.这里直接通过.bind(logger)人为的将其执行时的this指向logger对象。
bind()创建了一个函数,当这个函数在被调用的时候,它的this关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。
(二)setTimeout
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' + this.petalCount + ' petals!');
};
看一下这里this.dclare.bind(this),相当于将LateBloomer的实例对象传递到declare中,是不是setTimeout简洁了很多,同时不会破坏其他执行函数的结构。
(三)请完整阅读下面的代码
//设立一个简单地对象作为“上下文”
var context = {
foo: "bar"
};
//一个在this上下文中指向foo变量的函数
function returnFoo() {
return this.foo;
}
// 变量在作用域中不存在,因此显示undefined
returnFoo(); // => undefined
// 如果我们把它绑定在context上下文中
var bound = returnFoo.bind(context);
// 现在的作用域中有这个变量了
bound(); // => "bar"
//
// 这就是Function.prototype.bind的作用.
//由于returnFoo也是函数,因此它继承了function的原型
//
// 如果你觉得享受,接着往下读,下面更精彩
//
// 有许多方法将函数绑定在一个上下文中
// Call和Apply让你能在上下文中调用函数
returnFoo.call(context); // => bar
returnFoo.apply(context); // => bar
// 将函数添加到对象中
context.returnFoo = returnFoo;
context.returnFoo(); // => bar
//
// 现在我们来玩一点诡异的东西
//
// Array.prototype 中有一个叫做slice的方法
// 对一个数组调用slice,可以返回一个从start index到end index的数组
[1, 2, 3].slice(0, 1); // => [1]
// 因此我们把Array.slice赋值给一个本地变量slice
var slice = Array.prototype.slice;
//现在的slice是"自由的",由于Array.prototype中的slice一般指定了上下文
//或者默认为this,此时slice将不起作用
slice(0, 1); // => TypeError: can't convert undefined to object
slice([1, 2, 3], 0, 1); // => TypeError: ...
// 但是如果我们使用call或者apply,slice又将在一个上下文中执行
slice.call([1, 2, 3], 0, 1); // => [1]
// Apply和Call差不多,知识参数要放在一个数组中
slice.apply([1, 2, 3], [0, 1]); // => [1]
// 使用call没错了,那么能不呢使用bind呢?
// 没错,我们来把"call"绑定在slice上
slice = Function.prototype.call.bind(Array.prototype.slice);
// 现在slice可以把第一个参数作为上下文了
slice([1, 2, 3], 0, 1); // => [1]
//
// 很酷,对吧。现在再来完成一件事
//
// 现在我们对bind本身做一件刚才对silce做的事
var bind = Function.prototype.call.bind(Function.prototype.bind);
// 在这里总结一下,好好想想
// 发生了什么事? 我们改变了call,
// 返回一个接收一个函数和一个上下文作为ic桉树的函数
//并且返回了一个完全绑定的函数
// 回到最初的例子
var context = {
foo: "bar"
}; function returnFoo() {
return this.foo;
}
// 现在来使用神奇的"bind"函数
var amazing = bind(returnFoo, context);
amazing(); // => bar
Javascript中的bind()函数的更多相关文章
- JavaScript中的bind,call和apply函数的用法和区别
一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下 首先要理解的第一个概念,JavaScript中函数调用的方式, ...
- JavaScript中的普通函数和箭头函数
最近被问到了一个问题: javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答 ...
- 借助JavaScript中的时间函数改变Html中Table边框的颜色
借助JavaScript中的时间函数改变Html中Table边框的颜色 <html> <head> <meta http-equiv="Content-Type ...
- 前端学习 第二弹: JavaScript中的一些函数与对象(1)
前端学习 第二弹: JavaScript中的一些函数与对象(1) 1.apply与call函数 每个函数都包含两个非继承而来的方法:apply()和call(). 他们的用途相同,都是在特定的作用域中 ...
- 理解和使用 JavaScript 中的回调函数
理解和使用 JavaScript 中的回调函数 标签: 回调函数指针js 2014-11-25 01:20 11506人阅读 评论(4) 收藏 举报 分类: JavaScript(4) 目录( ...
- JavaScript中变量和函数声明的提升
现象: 1.在JavaScript中变量和函数的声明会提升到最顶部执行. 2.函数的提升高于变量的提升. 3.函数内部如果用var声明了相同名称的外部变量,函数将不再向上寻找. 4.匿名函数不会提升. ...
- javascript中使用md5函数
javascript中使用md5函数 这对于js来讲本来是没有的,现在可以自己定义一个md5的函数,达到加密效果. var hexcase = 0; function hex_md5(a) { if ...
- 在 JavaScript 中使用构造器函数模拟类
今天,我们要讲的是在 JavaScript 中使用构造器函数(construcor function)模拟类. 构造器函数简介 你可以使用 ES6 的 class 关键字来实现类,不过我建议你使用传统 ...
- 来一轮带注释的demo,彻底搞懂javascript中的replace函数
javascript这门语言一直就像一位带着面纱的美女,总是看不清,摸不透,一直专注服务器端,也从来没有特别重视过,直到最近几年,javascript越来越重要,越来越通用.最近和前端走的比较近,借此 ...
随机推荐
- codeforces 755C. PolandBall and Forest
C. PolandBall and Forest time limit per test 1 second memory limit per test 256 megabytes input stan ...
- PHP mysqli连接MySQL数据库
1. 开启PHP的API支持 (1)首先修改您的php.ini的配置文件.查找下面的语句:;extension=php_mysqli.dll将其修改为:extension=php_mysqli.dll ...
- 浅谈Java分页技术
话不多言.我们要实现java分页技术,我们首先就需要定义四个变量,他们是: int pageSize;//每页显示多少条记录 int pageNow;//希望现实第几页 int pageCount; ...
- 使用(Drawable)资源———ShapeDrawable资源
ShapeDrawable用于定义一个基本的几何图形(如矩形.圆形.线条等),定义ShapeDrawable的XML文件的根元素是<shape.../>元素,该元素可指定如下属性. and ...
- WinAPI: GetClassName - 获取指定窗口的类名
WinAPI: GetClassName - 获取指定窗口的类名 //声明: GetClassName( hWnd: HWND; {指定窗口句柄} lpClassName: PChar; {缓冲区} ...
- HDU-1996-汉诺塔VI
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1996 其实它就是求移动的所有可能,也就是n个盘子摆在三个塔上的任何可能的种数.可以这么思考这个问题:n ...
- GCD教程(一):基本概念
在网上看到关于GCD的一个很不错的教程,这里做一下转载 原帖地址:http://www.dreamingwish.com/dream-2012/of-of-of-of-gcd-introduced-1 ...
- 对angularjs时间过滤格式
在最近的项目中,我遇到这样的一个小问题,从后台传过来一个时间值,格式如下: "/Date(1484743002000)/" 至于为什么是这种格式,后台的开发说数据库中就是这个存的( ...
- ArcGIS制图表达Representation-制图表达原理
ArcGIS制图表达技术-制图表达原理 by 李远祥 在讲述原理之前,需要对上一章内容进行一些必要的补充说明.既然制图表达有很多优势,是不是什么情况下都可以使用制图表达技术呢?如果有以下的一些特殊的要 ...
- Web Worker无阻塞UI的牛逼技术,html5,可惜无法敢于UI
众所周知,JavaScript是单线程的,JS和UI更新共享同一个进程的部分原因是它们之间互访频繁,但由于共享同一个进程也就会造成js代码在运行的时候用户点击界面元素而没有任何响应这样的情况,这么糟糕 ...