每个JavaScript函数都会有很多附属的(attached)方法,包括toString()、call()以及apply()。听起来,你是否会 感到奇怪,一个函数可能会有属于它自己的方法,但是记住,JavaScript中的每个函数都是一个对象。看一下 这篇文章 ,复习一下(refresher)JavaScript特性。你可能还想知道JavaScript中函数和方法的区别。我认为“函数”和“方法”的描述, 仅仅是JavaScript的习惯约定而已。函数立足于它们自己(例如:alert()),而方法是函数内部一个对象的属性(dictionary),我 们通过对象来调用方法。每个JavaScript对象都有一个toString()方法,下面通过代码举例说明,在一个函数对象中,我们可以使用 toString()方法。

function foo(){
alert('x');
}
alert(foo.toString());

因为函数都是对象,它们有自己的属性和方法。我们可以把它们看作数据(data)。这篇文章,我们只关注两个函数的方法apply()以及call()。

我们从下面的代码开始:

var x = ;
function f(){
alert(this.x);
}
f();

我们定义了一个全局函数f()。f()通过this关键字访问变量x,但是需要注意的是,我们不能通过一个对象的实例来调用这个函数。this指向 的是什么对象呢?this会指向这个全局对象。我们的变量x就是在这个全局对象中定义的。上面的代码能够正常运行,运行结果会显示一个对话框,对话框中显 示10。

我们可以通过this来调用call()和apply()。正如下面的例子展示如何使用call():

var x = ;
var o = { x : };
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()也可以给函数传递参数:

var x = ;
var o = { x : };
function f(){
alert(this.x);
}
f();
f.call(o);

apply()和call()类似的,只是apply()要求第二个参数必须是一个数组。这个数组会作为参数传递给目标函数。

var x = ;
var o = {x : };
function f(message) {
alert(message);
alert(this.x);
}
f('invoking f');
f.apply(o, ['invoking f through apply']);

apply()方法是很有用的,因为我们可以创建一个函数而不用去关心目标方法的参数。这个函数可以通过apply()的第二个数组参数来传递额外的参数给方法。

var o = {x : };
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”。

function f(message) {
alert(message);
}
f('H', 'e', 'l', 'l', 'o');

在f()中,如果我们不想去接受其他的参数,我们可以用关键字arguments。arguments代表一个参数对象,它有一个代表长度的属性类似于数组。

function f(message) {
// message的值和arguments[0]是一样的
for(var i = ; 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()。

var o = {x : };
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 = ; 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。

JS call和apply用法(转)的更多相关文章

  1. JS Call()与Apply()

    JS Call()与Apply() ECMAScript规范给所有函数都定义了Call()与apply()两个方法,call与apply的第一个参数都是需要调用的函数对象,在函数体内这个参数就是thi ...

  2. js 中call,apply,bind的区别

    call.apply.bind方法的共同点与区别: apply.call.bind 三者都是用来改变函数的this对象的指向: apply.call.bind 三者都可以利用后续参数传参: bind ...

  3. [转载]js中return的用法

    一.返回控制与函数结果,语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制,无函数结果,语法为:return;  在大多数情况下,为事件处理函 ...

  4. js中this的用法

    经过近几周的模拟面试题,我查询了一些资料,今天就来说说,在js中this的用法吧.方法有四:第一,用作全局变量,第二,用作表该对象,第三,用作构造函数,第四,用作call和applay

  5. Join 和 apply 用法

    TSQL中的join语句共有五种类型,left join,right join,inner join,full join,cross join 为了描述方便,解释一个名词"保留表" ...

  6. JS 的 call apply bind 方法

    js的call apply bind 方法都很常见,目的都是为了改变某个方法的执行环境(context) call call([thisObj[,arg1[, arg2[,   [,.argN]]]] ...

  7. JQuery之append和appendTo的区别,还有js中的appendChild用法

    JQuery之append和appendTo的区别 append()前面是要选择的对象,后面是要在对象内插入的元素内容 appendTo()前面是要插入的元素内容且为Jquery对象,而后面是要选择的 ...

  8. JS中event.keyCode用法及keyCode对…

    js中event.keyCode用法及keyCode对照表 标签: javascriptJavaScriptJavascriptjavaScript 2012-12-11 15:11 HTML Jav ...

  9. 深入理解js中的apply、call、bind

    概述 js中的apply,call都是为了改变某个函数运行时的上下文环境而存在的,即改变函数内部的this指向. apply() apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作 ...

随机推荐

  1. Android学习笔记(七)两个Fragment简单跳转示例

    在前两篇博文中分别介绍了Fragment得基础和Fragment的生命周期,然而说了这么多Fragment到底怎么用呢以及我们为什么要使用Fragment?本篇博文将主要探讨这两个问题,首先说下在AP ...

  2. 中科院NLPIR中文分词java版

    中科院NLPIR中文分词java版 中科院NLPIR中文分词java版

  3. Please check if the Publishing Tools on the server (System/PublishingTools) are started.

    ArcMap或ArcCatalog中双击连接到Server即可,该工具即自动可启动

  4. 【转载】nginx 并发数问题思考:worker_connections,worker_processes与 max clients

    注:这个文章主要是作者一直在研究nginx作为http server和反向代理服务器时候所谓最大的max_clients和 worker_connections的计算公式, 其实最后的结论也没有卡上公 ...

  5. oracle REPLACE 函数 介绍

    oracle REPLACE 函数是用另外一个值来替代串中的某个值. 例如,可以用一个匹配数字来替代字母的每一次出现.REPLACE 的格式如下所示: REPLACE ( char, search_s ...

  6. oracle正则截取字符串的函数

    现在有这么一个需求, 数据库中的一个手输的'籍贯'字段,要按一定的规范截取显示在报表上,比如,如果'籍贯'的内容是:'山东省潍坊市昌乐县', 那么报表里要显示为:'山东昌乐', 如果'籍贯'是山东省潍 ...

  7. [ACM] HDU 5025 Saving Tang Monk (状态压缩,BFS)

    Saving Tang Monk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  8. 生成N个不重复的随机数(转)

    有25幅作品拿去投票,一次投票需要选16幅,单个作品一次投票只能选择一次.前面有个程序员捅了漏子,忘了把投票入库,有200个用户产生的投票序列为空.那么你会如何填补这个漏子? 当然向上级反映情况.但是 ...

  9. curl post参数,接口接收不到数据问题

    今天遇到一个问题,注册下发短信失败,总提示无法发送注册短信,请从新发送. 经检查,curl里面将post数据以json_encode的方法转码之后传递,而且各选项设置感觉没有问题,怎么接口就接收不到p ...

  10. iOS-设置状态栏白色以及覆盖状态栏

    iOS-设置状态栏白色以及覆盖状态栏 将状态栏设置为白色 首先, 在info.plist中添加一个标记. View controller–based status bar appearance键值设置 ...