JavaScript中的apply和call函数详解(转)
每个JavaScript函数都会有很多附属的(attached)方法,包括toString()、call()以及apply()。听起来,你是否会感到奇怪,一个函数可能会有属于它自己的方法,但是记住,JavaScript中的每个函数都是一个对象。看一下 这篇文章 ,复习一下(refresher)JavaScript特性。你可能还想知道JavaScript中函数和方法的区别。我认为“函数”和“方法”的描述,仅仅是JavaScript的习惯约定而已。函数立足于它们自己(例如:alert()),而方法是函数内部一个对象的属性(dictionary),我们通过对象来调用方法。每个JavaScript对象都有一个toString()方法,下面通过代码举例说明,在一个函数对象中,我们可以使用toString()方法。
|
1
2
3
4
|
function foo(){ alert('x'); } alert(foo.toString()); |
因为函数都是对象,它们有自己的属性和方法。我们可以把它们看作数据(data)。这篇文章,我们只关注两个函数的方法apply()以及call()。
我们从下面的代码开始:
|
1
2
3
4
5
|
var x = 10; function f(){ alert(this.x); } f(); |
我们定义了一个全局函数f()。f()通过this关键字访问变量x,但是需要注意的是,我们不能通过一个对象的实例来调用这个函数。this指向的是什么对象呢?this会指向这个全局对象。我们的变量x就是在这个全局对象中定义的。上面的代码能够正常运行,运行结果会显示一个对话框,对话框中显示10。
我们可以通过this来调用call()和apply()。正如下面的例子展示如何使用call():
|
1
2
3
4
5
6
7
|
var x = 10; var o = { x : 15}; function f(){ alert(this.x); } f(); f.call(o); |
首先调用f()将会显示10的对话框,因为this这个时候指向的是全局对象。然后我们调用f函数的call()方法,传入的参数是o,运行结果显示的是o中x属性的值15。call()方法会用它的第一个参数作为f函数的this指针。也就是说,我们会告诉运行时,f函数中的this指向的是哪个对象。
this跳转听起来有些滑稽,甚至对于C++、Java以及C#程序员来说有些反常。这些都是ECMAScript中有趣的部分。
通过call()也可以给函数传递参数:
|
1
2
3
4
5
6
7
|
var x = 10; var o = { x : 15}; function f(){ alert(this.x); } f(); f.call(o); |
apply()和call()类似的,只是apply()要求第二个参数必须是一个数组。这个数组会作为参数传递给目标函数。
|
1
2
3
4
5
6
7
8
|
var x = 10; var o = {x : 15}; function f(message) { alert(message); alert(this.x); } f('invoking f'); f.apply(o, ['invoking f through apply']); |
apply()方法是很有用的,因为我们可以创建一个函数而不用去关心目标方法的参数。这个函数可以通过apply()的第二个数组参数来传递额外的参数给方法。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
var o = {x : 15}; function f1(message1) { alert(message1 + this.x); } function f2(message1, message2) { alert(message1 + (this.x * this.x) + message2); } function g(object, func, args) { func.apply(object, args); } g(o, f1, ['the value of x = ']); g(o, f2, ['the value of x squared = ', '. Wow!']); |
这样的语法有点问题。为了调用apply()方法,我们强制目标函数使用数组中的参数。幸运的是,有一个方法可以让这种语法更简单。在此之前,我们必须先介绍一个:参数标识符。
在JavaScript中,其实每个函数都有一个可变长度的参数列表。这意味着,即使一个函数只有一个参数的时候,我们也可以传递5个参数给它。下面的代码不会有错误,而且结果显示的是“H”。
|
1
2
3
4
|
function f(message) { alert(message); } f('H', 'e', 'l', 'l', 'o'); |
在f()中,如果我们不想去接受其他的参数,我们可以用关键字arguments。arguments代表一个参数对象,它有一个代表长度的属性类似于数组。
|
1
2
3
4
5
6
7
8
9
|
function f(message) { // message的值和arguments[0]是一样的 for(var i = 1; i < arguments.length; i++){ message += arguments[i]; } alert(message); } // 结果显示“Hello” f('H', 'e', 'l', 'l', 'o'); |
你应该知道,严格来讲,arguments不是一个数组。arguments有一个length属性,但是没有split、push、pop方法。在前面的g()函数中,我们可以从arguments中拷贝需要的参数,组成数组,然后把这个数组传递给apply()。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var o = {x : 15}; function f(message1, message2) { alert(message1 + ( this.x * this.x) + message2); } function g(object, func) { // arguments[0] = object // arguments[1] = func var args = []; for(var i = 2; i < arguments.length; i++) { args.push(arguments[i]); } func.apply(object, args); } g(o, f, 'The value of x squared = ', '. Wow!'); |
当我们调用g(),we can pass additional arguments as parameters instead of stuffing the arguments into an array。
JavaScript中的apply和call函数详解(转)的更多相关文章
- JavaScript中的apply和call函数详解
本文是翻译Function.apply and Function.call in JavaScript,希望对大家有所帮助 转自“http://www.jb51.net/article/52416.h ...
- javascript 中的apply()和call()方法详解
1.语法 先来看看JS手册中对call的解释: call 方法 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1[, arg2[, [,.argN]]]]]) ...
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- Pythonh中的zip()与*zip()函数详解
前言 实验环境: Python 3.6: 示例代码地址:下载示例: 本文中元素是指列表.元组.字典等集合类数据类型中的下一级项目(可能是单个元素或嵌套列表). zip(*iterables)函数详解 ...
- Javascript中的url编码与解码(详解)
摘要 本文主要针对URI编解码的相关问题做了介绍,对url编码中哪些字符需要编码.为什么需要编码做了详细的说明,并对比分析了Javascript中和编解码相关的几对函数escape / unescap ...
- Python中的zip()与*zip()函数详解
前言 实验环境: Python 3.6: 示例代码地址:下载示例: 本文中元素是指列表.元组.字典等集合类数据类型中的下一级项目(可能是单个元素或嵌套列表). zip(*iterables)函数详解 ...
- JavaScript中的this的指代对象详解
在javascript里面,this是一个特殊的对象,它不像其他编程语言那样,是存储在实例中的值,直接指向此实例. 而是作为一个单独的指针,在不同的情况之下,指向不同的位置,这也是为什么我们会将它搞混 ...
- javascript中parentNode,childNodes,children的应用详解
本篇文章是对javascript中parentNode,childNodes,children的应用进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 "parentNode&qu ...
随机推荐
- About_Return
返回值:return return 表示从被调函数返回到主调函数继续执行,返回时可附带一个返回值,由return后面的参数指定. return通常是必要的,因为函数调用的时候计算结果通常是通过返回值带 ...
- Screen Orientation for Windows Phone
http://msdn.microsoft.com/en-us/library/windows/apps/jj207002(v=vs.105).aspx
- 判断.NET4.0是否安装
Clinet 和 Full存在一个都说明安装了Framework "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client"&qu ...
- *HDU2510 DFS
符号三角形 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- Swift微博编写感
首先Swift是苹果2014年力推的编程语言.可见发展趋势 在此提供
- 将List下载到本地保存为Excel
直接附上代码 /// <summary> /// 将List保存为Excel /// </summary> /// <typeparam name="T&quo ...
- ubuntu segmentation fault 段错误
1.段错误 http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 2.段错误的调试方法 2.1使用printf输出信息 2 ...
- 巧妙利用before和after伪类实现文字的展开和收起
需求:一段文字,当收起的时候,显示4行,并且多余4行的部分用省略号表示,关键是在省略号前面留有空白部分来放一些图标等东西:展开的时候,全部显示. 例如下面的示例图: 收起的时候: 展开的时候: 在不用 ...
- Windows 7 IE主页被篡改,如何修复?
有时我们的电脑会因为病毒的入侵,使得IE主页被篡改,然后就会被没底线的广告包围,有时用杀毒软件也不修复,那么此时应该怎么修复呢?其实很简单,只需几步,就可以让您的电脑重新清净下来. 第一步 点击“开始 ...
- Socket--Java
Server.java package socket; import java.io.BufferedReader; import java.io.DataInputStream; import ja ...