简要谈谈javascript bind 方法
最近去参加了场面试,跟面试官聊了很多JS基础上的东西,其中有个问题是谈谈对apply、call、bind的理解和区别。顿时一愣,apply、call我知道,经常用的东西,bind是什么鬼!!!好像见过,也瞅过类似的文章,但是...不记得了...难道和jQuery的事件绑定的bind一样...

既然不知道,那就整理总结下啰~
一、apply和call
既然提到提到了这两兄弟,也跟着简单做下知识整理。在javascript中,this的指向是一个经常要处理的问题。比较经典的一个问题就是,document.getElementById太长了,敲着好累好烦,用一个短点的方法,对它进行封装一下,就下面这样,两行代码搞定,多么简单~
<div id="test"></div>
<script>
var getDom = document.getElementById;
console.log(getDom("test"))
</script>
但是。。。调用时,系统提示Uncaught TypeError: Illegal invocation 啊..........这是什么鬼错误 !其实这就是this的问题,使用document.getElementById,函数执行时this指向document,但是使用getDom,函数执行时,this指向的是window。而在getElementById在内核实现中又使用了this,so 就报错了啰!!!
正确的封装方式为:(即用apply/call设定下函数调用时的this指向)
<div id="test"></div>
<script>
var getDom = (function(func){
return function(){
return func.apply(document , arguments);
}
})(document.getElementById);
console.log(getDom("test"))
</script>
总结:apply和call的用法是一致的,就是改变和确定函数执行时的this指向,区别就是apply后一个参数是数组,call后是一堆参数。话不多说,进入正题....
二、bind基本
首先来谈谈它跟apply/call的区别,bind方法返回的是一个函数,不会立即执行,待用()调用时才会执行,而apply/call则是立即执行函数。
MDN的解释是:bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
接下来用demo简单使用下
1、单纯的绑定this
var person1 = {
name : "sky" ,
getName : function(){
return this.name;
}
}
var person2 = {name : "moon"};
var getName = person1.getName.bind(person2); //绑定person2作为getName函数执行的this
console.log(getName()); //打印的值为moon
这样用法比较简单
2、传参数的形式
var self = {name : "sky" , age: 26}
var getDescription = function(country , city){
console.log("my name is " + this.name + " , my age is " + this.age + " , I'am from " + country + " " + city);
}.bind(self , "China");
getDescription("WuHan"); //my name is sky , my age is 26 , I'am from China WuHan
个人感觉,这种就是相当于通过bind方法预设一些参数,比如此时就是预设的country参数,调用时在传递动态的参数,比如这里的WuHan。通过这样的方式绑定this,配合预设参数,灵活程度十分的高
三、bind的使用场景
水平有限,仅谈谈个人。我在多层函数嵌套的代码编写中,喜欢使用var _this = this;来保存上级函数作用域中的this,这样在内嵌的函数中就是可以用_this获取上级作用域的this。如果用bind则可以换一种方式,具体对比如下:
<div id="test1">test1</div>
<div id="test2">test2</div>
<script>
//旧写法,使用_this保存
var tool1 = {
name: "sky1",
bindEvent: function() {
var _this = this;
document.getElementById("test1").addEventListener("click", function() {
console.log(_this.name)
}, false)
}
}
//新写法,使用bind绑定
var tool2 = {
name: "sky2",
bindEvent: function() {
document.getElementById("test2").addEventListener("click", function() {
console.log(this.name)
}.bind(this), false)
}
}
tool1.bindEvent();
tool2.bindEvent();
</script>
怎么说呢,代码看起来更加优美一些把....我是颜值控
四、bind 兼容性
bind方法是ES5中扩展的方法,所以IE6、7、8均不兼容...整个人都不好了

怎么办呢,网上有一堆的兼容资料,我比较喜欢自己造轮子...其实也蛮简单的,就是apply/call的封装使用,学习嘛,循序渐进的来,分成两步,以下均用skyBind方法表示...
1、仅仅实现修改执行环境即this的功能
Function.prototype.skyBind = function(context){
var func = this; //就是它!!!这个func就是需要执行,且要绑定context的函数!!!!!!
return function(){
return func.apply(context , arguments); //绑定且执行
}
}
var person1 = {
name : "sky" ,
getName : function(){
return this.name;
}
}
var person2 = {name : "moon"};
var getName = person1.getName.skyBind(person2);
console.log(getName()); //打印的值为moon
很简单有没有!!!
2、加入传参的功能
Function.prototype.skyBind = function(){
var func = this , //还是它!!!这个func就是需要执行,且要绑定context的函数!!!!!!
context = [].shift.call(arguments) , //此时传入的参数就不单单有this的指向,还是其他的参数,按规定第一个参数就是执行环境,拿到它
args = [].slice.call(arguments); //arguments具有数组的属性,毕竟JS是个弱类型的语言,但是它毕竟不是数组,用这个方法就是把arguments转换成数组,不用slice换成splice或者其他的都行
return function(){
/* 绑定且执行,执行函数的参数为两个数组的合并
* 这里需要解释的是args是bind绑定时传入的参数,比如下面demo中的China,而下面的arguments则是实际调用时传入的参数WuHan
* */
return func.apply(context , [].concat(args , [].slice.call(arguments) ));
}
}
//demo
var self = {name : "sky" , age: 26}
var getDescription = function(country , city){
console.log("my name is " + this.name + " , my age is " + this.age + " , I'am from " + country + " " + city);
}.skyBind(self , "China");
getDescription("WuHan"); //my name is sky , my age is 26 , I'am from China WuHan
搞定!!!
简要谈谈javascript bind 方法的更多相关文章
- 谈谈javascript数组排序方法sort()的使用,重点介绍参数使用及内部机制?
语法:arrayObject.sort(sortby) 参数sortby可选,规定排序顺序,必须是函数: 注:如果调用该方法时没有使用参数,将按字符编码的顺序进行排序,要实现这一点,首先应把数组的元素 ...
- Javascript中call,apply,bind方法的详解与总结
在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...
- 如何在JavaScript中正确引用某个方法(bind方法的应用)
在JavaScript中,方法往往涉及到上下文,也就是this,因此往往不能直接引用,就拿最常见的console.log("info…")来说,避免书写冗长的console,直接用 ...
- javascript中函数的call,apply及bind方法
call 方法调用一个对象的一个方法,以另一个对象替换当前对象.call([thisObj[,arg1[, arg2[, [,.argN]]]]])参数thisObj可选项.将被用作当前对象的对象. ...
- 《JavaScript总结》apply、call和bind方法
在JavaScript中,apply.call.bind这个三个方法,它们的作用都是为了改变某个函数运行时的上下文, 也就是改变函数体内的this指向. 在一个函数里,存在“定义时上下文”.“运行时上 ...
- 浅析 JavaScript 中的 Function.prototype.bind() 方法
Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个对象,bind() 方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数 ...
- javascript原生bind方法详解
bind()方法,是javascript原生的函数类的一个原型方法(即Function.prototype里的方法),不支持ie低版本. 基本格式: function.bind(obj1,obj2,o ...
- JavaScript中的call、apply、bind方法的区别
在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这 ...
- javascript原生bind方法ie低版本兼容详解
上一篇文章讲到了javascript原生的bind方法: http://www.cnblogs.com/liulangmao/p/3451669.html 这篇文章就在理解了原生bind方法的原理以后 ...
随机推荐
- beego——过滤器
beego支持自定义过滤中间件,例如安全验证.强制跳转等. 过滤器函数如下所示: beego.InsertFilter(pattern string, position int, filter Fil ...
- 杭电1023Train Problem II
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1023 题目: Train Problem II Time Limit: 2000/1000 MS (Jav ...
- HYSBZ - 2243 染色 (树链剖分+线段树)
题意:树上每个结点有自己的颜色,支持两种操作:1.将u到v路径上的点颜色修改为c; 2.求u到v路径上有多少段不同的颜色. 分析:树剖之后用线段树维护区间颜色段数.区间查询区间修改.线段树结点中维护的 ...
- 跟着实例学习ZooKeeper的用法: 分布式锁
锁 分布式的锁全局同步, 这意味着任何一个时间点不会有两个客户端都拥有相同的锁. 可重入锁Shared Reentrant Lock 首先我们先看一个全局可重入的锁. Shared意味着锁是全局可见的 ...
- hadoop15---activemq
java JMS技术 JMS是规范,activeMQ是实现. 用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信. 它类似于JDBC,JDBC 是可以用来访问许多不同关系数据库的 API. ...
- 最小可用 Spring MVC 配置
[最小可用 Spring MVC 配置] 1.导入有概率用到的JAR包, -> pom.xml 的更佳实践 - 1.0 <- <project xmlns="http:// ...
- jQuery二级下拉菜单
在线演示 本地下载
- docker 在windows上的使用
Docker ToolBox 安装 1.首先,安装Docker ToolBox,其中包含了Docker三剑客: docker , docker-machine 和 docker-compose . 安 ...
- Python 私有化属性
# 对象的基本理论 # 什么事对象? # 万物皆对象 # 对象是具体物体 # 拥有属性 # 拥有行为 # 把很多零散的东西,封装成为一个整体 # 举例:王二小 # 属性 # 姓名 # 年龄 # 身高 ...
- 使用nagios检测windows服务器
1.安装nagios windows客户端 下载NSClient++的安装包,注意根据实际的32/64CPU来下载 下载地址 http://sourceforge.net/projects/nscpl ...