JavaScript中的apply和call函数详解


Posted in Javascript onJuly 20, 2014

第一次翻译技术文章,见笑了!

翻译原文:

Function.apply and Function.call in JavaScript

第一段略。

每个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 = 10;
function f(){
 alert(this.x);
}
f();

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

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

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()也可以给函数传递参数:

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

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

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()的第二个数组参数来传递额外的参数给方法。

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”。

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

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

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()。

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 相关文章推荐
js程序中美元符号$是什么
Jun 05 Javascript
杨氏矩阵查找的JS代码
Mar 21 Javascript
jQuery登陆判断简单实现代码
Apr 21 Javascript
使用JQuery实现的分页插件分享
Nov 05 Javascript
javascript类型系统_正则表达式RegExp类型详解
Jun 24 Javascript
AngularJS 入门教程之事件处理器详解
Aug 19 Javascript
D3.js实现直方图的方法详解
Sep 25 Javascript
jquery在启动页面时,自动加载数据的实例
Jan 22 jQuery
在vue里使用codemirror遇到的问题
Nov 01 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
Dec 02 Javascript
JS函数动态传递参数的方法分析【基于arguments对象】
Jun 05 Javascript
vue@cli3项目模板怎么使用public目录下的静态文件
Jul 07 Javascript
一行命令搞定node.js 版本升级
Jul 20 #Javascript
JavaScript中的原型和继承详解(图文)
Jul 18 #Javascript
JavaScript中伪协议 javascript:使用探讨
Jul 18 #Javascript
js清空表单数据的两种方式(遍历+reset)
Jul 18 #Javascript
js使用正则实现ReplaceAll全部替换的方法
Jul 18 #Javascript
javascript原生和jquery库实现iframe自适应高度和宽度
Jul 18 #Javascript
关于javaScript注册click事件传递参数的不成功问题
Jul 18 #Javascript
You might like
php筛选不存在的图片资源
2015/04/28 PHP
IIS 7.5 asp Session超时时间设置方法
2017/04/17 PHP
PHP 进程池与轮询调度算法实现多任务的示例代码
2019/11/26 PHP
jQuery实现公告文字左右滚动的实例代码
2013/10/29 Javascript
浅析JavaScript中的隐式类型转换
2013/12/05 Javascript
JavaScript日期类型的一些用法介绍
2015/03/02 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
2015/05/01 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
2015/08/25 Javascript
很全面的JavaScript常用功能汇总集合
2016/01/22 Javascript
基于Bootstrap分页的实例讲解(必看篇)
2017/07/04 Javascript
通过命令行生成vue项目框架的方法
2017/07/12 Javascript
Vue官方文档梳理之全局配置
2017/11/22 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
使用electron实现百度网盘悬浮窗口功能的示例代码
2018/10/24 Javascript
微信小程序+腾讯地图开发实现路径规划绘制
2019/05/22 Javascript
react中Suspense的使用详解
2019/09/01 Javascript
JavaScript this使用方法图解
2020/02/04 Javascript
[03:24][TI9纪实] Dota奶爸
2019/08/22 DOTA
Python写的一个定时重跑获取数据库数据
2016/12/28 Python
Python实现的旋转数组功能算法示例
2019/02/23 Python
python环境下安装opencv库的方法
2020/03/05 Python
Pytorch十九种损失函数的使用详解
2020/04/29 Python
Python实现寻找回文数字过程解析
2020/06/09 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
python设置表格边框的具体方法
2020/07/17 Python
pytorch中index_select()的用法详解
2021/01/06 Python
美国花园雕像和家居装饰网上商店:Design Toscano
2019/03/09 全球购物
英国领先的在线礼品店:Getting Personal
2019/09/24 全球购物
商务英语专业毕业生自荐信
2013/11/05 职场文书
网吧最新创业计划书范文
2014/03/27 职场文书
银行求职信怎么写
2014/05/26 职场文书
乡镇安全生产目标责任书
2014/07/23 职场文书
商家认证委托书格式
2014/10/16 职场文书
2015年医院工作总结范文
2015/04/09 职场文书
Python装饰器的练习题
2021/11/23 Python
用Python可视化新冠疫情数据
2022/01/18 Python