JavaScript中bind、call、apply函数使用方法具体解释
在给我们项目组的其它程序介绍 js 的时候,我准备了非常多的内容,但看起来效果不大,果然光讲还是不行的,必须动手。
前几天有人问我关于代码里 call() 函数的使用方法。我让他去看书,这里推荐用js 写server的程序员看《javascript编程精粹》 这本书。crockford大神果然不是盖的。之后我在segmentfault上又看到了类似的问题。那边解答之后干脆这里记一笔。
首先,关于 js 定义类或对象的方法,请參看w3school 的这里的这里,写的很具体和清晰,我不再赘言了。

为了介绍 bind、call、apply 这三个函数的使用方法,不得不介绍 js 里函数的一些设定。关于这部分推荐通读 《javascript编程精粹》 的第四章。这里我所说的在书里都能找到。
关于这三个函数的具体介绍。能够參看 MDN 的文档:bind、call、apply。
以下開始搬砖,改动自我之前在 segmentfault 上的答案:
js 里函数调用有 4 种模式:方法调用、正常函数调用、构造器函数调用、apply/call 调用。
同一时候,不管哪种函数调用除了你声明时定义的形參外,还会自己主动加入 2 个形參,各自是 this 和arguments。
arguments 不涉及到上述 3 个函数,所以这里仅仅谈 this。this 的值,在上面 4 中调用模式下,分别会绑定不同的值。分别来说一说:
方法调用:
这个非常好理解,函数是一个对象的属性。比方
var a = {
v : 0,
f : function(xx) {
this.v = xx;
}
}
a.f(5);
这个时候,上面函数里的 this 就绑定的是这个对象 a。
所以 this.v 能够取到对象 a 的属性 v。
正常函数调用:依旧看代码
function f(xx) {
this.x = xx;
}
f(5);
这个时候。函数 f 里的 this 绑定的是全局对象,假设是在浏览器执行的解释器中。一般来说是 window 对象。所以这里 this.x 訪问的事实上是 window.x 。当然,假设 window 没有 x 属性,那么你这么一写,依照 js 的坑爹语法。就是给 window 对象加入了一个 x 属性,同一时候赋值。
构造器函数调用:
构造函数一直是我觉得是 js 里最坑爹的部分。由于它和 js 最初设计的基于原型的面向对象实现方式格格不入,就好像是特意为了迎合大家已经被其它基于类的面相对象实现给惯坏了的习惯。
假设你在一个函数前面带上 new keyword来调用,那么 js 会创建一个 prototype 属性是此函数的一个新对象,同一时候在调用这个函数的时候,把 this 绑定到这个新对象上。
当然 new keyword也会改变return 语句的行为,只是这里就不谈了。看代码
function a(xx)
{
this.m = xx;
}
var b = new a(5);
上面这个函数和正常调用的函数写法上没什么差别,仅仅只是在调用的时候函数名前面加了keyword new罢了,这么一来,this 绑定的就不再是前面讲到的全局对象了。而是这里说的创建的新对象。所以说这样的方式事实上非常危急。由于光看函数。你不会知道这个函数究竟是准备拿来当构造函数用的。还是一般函数用的。所以我们能够看到。在 jslint 里,它会要求你写的全部构造函数,也就是一旦它发现你用了 new keyword,那么后面那个函数的首字母必须大写,这样通过函数首字母大写的方式来区分。我个人仅仅有一个看法:坑爹:)
apply/call 调用:
我们知道,在 js 里,函数事实上也是一个对象,那么函数自然也能够拥有它自己的方法,有点绕。在js 里,每一个函数都有一个公共的 prototype —— Function,而这个原型自带有好几个属性和方法,当中就有这里困惑的 bind、call、apply 方法。先说 apply 方法,它让我们构造一个參数数组传递给函数。同一时候能够自己来设置 this 的值。这就是它最强大的地方,上面的 3 种函数调用方式,你能够看到,this 都是自己主动绑定的,没办法由你来设,当你想设的时候,就能够用 apply()了。apply
函数接收 2 个參数。第一个是传递给这个函数用来绑定 this 的值,第二个是一个參数数组。
看代码
function a(xx) {
this.b = xx;
}
var o = {};
a.apply(o, [5]);
alert(a.b); // undefined
alert(o.b); // 5
是不是非常奇妙。函数 a 竟然能够给 o 加属性值。
当然。假设你 apply 的第一个參数传递 null,那么在函数 a 里面 this 指针依旧会绑定全局对象。
call() 方法和 apply() 方法非常类似,它们的存在都是为了改变 this 的绑定。那 call() 和apply() 有什么差别呢?就我个人看来。没啥鸟差别。
。。开玩笑!刚刚说了,上面 apply() 接收两个參数,第一个是绑定 this 的值,第二个是一个參数数组,注意它是一个数组。你想传递给这个函数的全部參数都放在数组里,然后 apply() 函数会在调用函数时自己主动帮你把数组展开。
而 call()呢,它的第一个參数也是绑定给 this 的值。可是后面接受的是不定參数,而不再是一个数组,也就是说你能够像平时给函数传參那样把这些參数一个一个传递。
所以假设一定要说有什么差别的话。看起来是这种
function a(xx, yy) {
alert(xx, yy);
alert(this);
alert(arguments);
}
a.apply(null, [5, 55]);
a.call(null, 5, 55);
仅此而已。
最后再来说 bind() 函数,上面讲的不管是 call() 也好, apply() 也好,都是立刻就调用了相应的函数。而 bind() 不会。 bind() 会生成一个新的函数,bind() 函数的參数跟 call() 一致,第一个參数也是绑定 this 的值,后面接受传递给函数的不定參数。 bind() 生成的新函数返回后,你想什么时候调就什么时候调,看下代码就明确了
var m = {
"x" : 1
};
function foo(y) {
alert(this.x + y);
}
foo.apply(m, [5]);
foo.call(m, 5);
var foo1 = foo.bind(m, 5);
foo1();
末了来个吐槽,你在 js 里想定义一个函数,于是你会这么写:
function jam() {};
事实上这是 js 里的一种语法糖。它等价于:
var jam = function() {};
然后你想运行这个函数,脑洞大开的你会这么写:
function jam() {}();
可是这么写就报错了,事实上这样的写法也不算错。由于它确实是 js 支持的函数表达式。可是同一时候 js 又规定以function 开头的语句被觉得是函数语句。而函数语句后面是肯定不会带 () 的,所以才报错,于是聪明的人想出来,加上一对括号就能够了。于是就变成了这样:
1(function jam() {}());
这样就定义了一个函数同一时候也运行它。详情參加 ECMAScript 的 Expression Statement 章节。
以上摘自码农网:http://www.codeceo.com/article/javascript-bind-call-apply.html
原文来自菜鸟浮出水的博客:http://rangercyh.blog.51cto.com/1444712/1615809
JavaScript中bind、call、apply函数使用方法具体解释的更多相关文章
- 面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗
一.前言 不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数 ...
- Javascript中call、apply函数浅析
call/apply函数作用其实就是改变this的取值,有一句话是:谁调用的这个方法那方法里的this就是指谁,而有时我们会需要改变this值,所以call/apply就能派上用场. 下面我写个方法来 ...
- 博文推荐】Javascript中bind、call、apply函数用法
[博文推荐]Javascript中bind.call.apply函数用法 2015-03-02 09:22 菜鸟浮出水 51CTO博客 字号:T | T 最近一直在用 js 写游戏服务器,我也接触 j ...
- 说说 JavaScript中 call和apply
下面有关JavaScript中 call和apply的描述,错误的是? call与apply都属于Function.prototype的一个方法,所以每个function实例都有call.apply属 ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- 使用Ajax在javascript中调用后台C#函数
使用Ajax在javascript中调用后台C#函数 最近一段时间在紧跟一个网站的项目,数据库中用户表的UserName要求是唯一的,所以当用户选定一个用户名进行注册时要首先检查该用户名是否已被占用, ...
- 在javascript中关于变量与函数的提升
在javascript中关于变量与函数的提升 一.简介 在javascript中声明变量与函数的执行步骤: 1.先预解析变量或函数声明代码,会把用var声明的变量或者函数声明的代码块进行提升操作 2. ...
- javascript中的立即执行函数(function(){…})()
javascript中的立即执行函数(function(){…})() 深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包 ...
- JQuery中bind和unbind函数与onclick绑定事件区分
JQuery中bind和unbind函数转载: https://blog.csdn.net/liucheng417/article/details/51131982 页面代码: <body& ...
随机推荐
- 微信图片不可显示java解决方法
先看知乎:https://www.zhihu.com/question/35044484 场景: 微信上传了图片素材,返回了图片url,然后不能在img标签中正常显示. 原因是微信做了图片防盗连接. ...
- 【原创】.Net 微信 JS-SDK图片、语音上传接口的实现(MVC)-(一 、上传图片)
前段时间在做一个微信的项目,遇到了一个上传图片的问题,花了一下午,解决了这个问题,然后把总结出来的代码,分享了出来. 最近又有一个图片+语音的功能, 更是蛋疼, 本次采用的不是File文件上传,然后转 ...
- MySQL Connector for .NET 和 EF版本匹配问题
以下讨论的都是EF5.0, 版本号:4.4.0.0 如果装了MySQL 5.0.1 , 那么最好用MySQL Connector 6.3.6,但是创建数据库后,生成迁移历史表的时候,会报错,你不管,直 ...
- dubbo之分组聚合
按组合并返回结果 ,比如菜单服务,接口一样,但有多种实现,用group区分,现在消费方需从每种group中调用一次返回结果,合并结果返回,这样就可以实现聚合菜单项. 相关代码可以参考 dubbo 项目 ...
- texi格式文件的读取
使用texi2html可以将texi格式的文件转换成html格式的文件. sudo apt-get install texi2html 在对应目录下 texi2html filename.texi 或 ...
- AS3.0+PHP写入mySQL
php中$_POST变量是一个数组,用于收集来自method="post"的值,内容是有HTTP POST方法发送的变量名称和值. 从带有POST方法的表单发送的信息,对任何人都是 ...
- idea搭建第一个springboot
1.打开idea开发工具,在菜单栏选择File-->New-->Project...-->Spring Initializer说明:社区版的idea是没有Spring Initial ...
- 关于JsonArray与JsonObject的使用
学习地址:http://blog.csdn.net/lishuangzhe7047/article/details/28880009 关于前台向后台传递数组(里面包含json格式) [{"i ...
- inherit 关键字使得元素获取其父元素的计算值
它可以应用于任何CSS属性,包括CSS简写 all. 对于继承属性,inherit 关键字只是增强了属性的默认行为,只有在重载(overload)其它规则的时候被使用.对于非继承属性,inherit ...
- 【C#】【分享】 XXX分钟学会C#
原文地址 https://www.cnblogs.com/younShieh/p/10945264.html 前几天在刷即刻的时候发现了一个GitHub上的项目,该项目名为"lear ...