玩转方法:call和apply


Posted in Javascript onMay 08, 2014

在ECMAScript v3中,给Function原型定义了这两个方法,这两个方法的作用都是一样的:使用这两个方法可以像调用其他对象方法一样调用函数,这句话是从书上抄的,至少我是没读明白这是什么意思。
下面说简单易懂的,先看段代码:

function Introduce(name,age) 
{ 
    document.write("My name is "+name+".I am "+age); 
} 
var p=new People(); 
Introduce.call(p,"Windking",20);

就说上面的这段代码,用了call之后,Introduce就成了p的方法,不知道这样说你明白了么?使用了call方法,上述的代码就等同于了这个代码:

function People(name,age) 
{ 
    this.name=name; 
    this.age=age; 
    this.Introduce=function(){ 
document.write("My name is "+name+".I am "+age); 
}; 
}

明白意思了么?apply也是一样的作用。
好,我们不管这个方法到底能在实际中用到什么,先讲语法。
call接受至少一个参数,call的第一个参数是指你所需要的对象,比如说上面的那个例子,Introduce方法希望他能够被对象p所调用,那么就把p作为call的第一个参数。剩余的参数个数是任意的,作用是作为Introduce方法的参数。顺序按照Introduce参数声明的顺序。比如Introduce.call(p,"Windking",20),假如Introduce是p的一个实例方法,那么也就是这样的:p.Introduce("Windking",20)。明白了么?记住,传入参数的顺序要与函数声明参数的顺序保持一致。
了解了call,apply方法就容易理解了,apply和call唯一的区别是call接受至少一个参数,而apply只接受两个参数,第一个参数与call一样,第二个参数是一个带下标的集合,比如说Introduce.call(p,"Windking",20)就可以改写成Introduce.apply(p,["Windking",20])了。这次明白了么?
那究竟这两个方法有什么用呢?如果我们只是为了实现上面的那个功能,把Introduce实现为People的方法不是更好么?

我把应用总结为两条:

1.共享方法。先看代码:

function Introduce(name,age) 
{ 
        document.write("My name is "+name+".I am "+age); 
}

这是一个自我介绍的方法,现在假设我们有一个男孩的类,和一个女孩的类(在这里我只是为了演示,在实际中,会用一个People的父类),因为他们的Introduce都是一样的,于是我们就可以共享这个方法。

function Boy() 
{ 
        this.BoyIntroduce=function(){ 
Introduce.call(this,name,age); 
}; 
}

同理,Girl中也是一样,这样的话,我们就可以避免写代码了。其实这个有些牵强,因为我们完全也可以写成:

function Boy() 
{ 
        this.BoyIntroduce=function(){ 
            Introduce(name,age); 
} 
}

但是这个时候,我们如果用Apply的话,就看上去简单多了:

function Boy() 
{ 
        this.BoyIntroduce=function(){ 
Introduce.apply(this,arguments); 
}; 
}

是不是简单了很多呢?如果参数很多的话,那么是不是不用再写那么一场串密密麻麻的参数了呢!

2.跨域调用

看一个简单的例子(仅为演示,无任何价值):

function Boy(name,age) 
{ 
        this.BoyIntroduce=function(){ 
            document.write("My name is "+name+".I am "+age); 
} 
} 
function Girl(name,age) 
{ }

这是一个Boy和一个Girl类,然后我们写如下的代码:

var b=new Boy("Windking",20);
b.BoyIntroduce();

这没有任何异议。假设有一天有一个女孩也希望做一下自我介绍,只是偶然用一下,那么我就没有必要修改Girl类,因为其他的女孩比较害羞,不喜欢自我介绍。那么这个时候我就可以这样。

var g=new Girl("Xuan",22);
Introduce.call(g,"Xuan",22);

3.真正用处——继承

好了,上面都是雕虫小技,不登大雅之堂,下面才是call和apply最广泛的应用,就是用于构造继承。

Javascript 相关文章推荐
用js得到网页中所有的div的id
Oct 19 Javascript
理解Javascript_08_函数对象
Oct 15 Javascript
javascript 判断中文字符长度的函数代码
Aug 27 Javascript
jquerymobile局部渲染的各种刷新方法小结
Mar 05 Javascript
jQuery回到顶部的代码
Jul 09 Javascript
Bootstrap实现input控件失去焦点时验证
Aug 04 Javascript
jQuery插件zTree实现获取一级节点数据的方法
Mar 08 Javascript
js使用i18n实现页面国际化的方法
May 09 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
Jun 30 Javascript
js学习总结之DOM2兼容处理重复问题的解决方法
Jul 27 Javascript
vue-cli 引入、配置axios的方法
May 08 Javascript
前端JS获取URL参数的4种方法总结
Apr 05 Javascript
jQuery产品间断向下滚动效果核心代码
May 08 #Javascript
jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
May 08 #Javascript
jquery通过visible来判断标签是否显示或隐藏
May 08 #Javascript
setInterval计时器不准的问题解决方法
May 08 #Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 #Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
May 08 #Javascript
js 设置缓存及获取设置的缓存
May 08 #Javascript
You might like
PHP面向对象——访问修饰符介绍
2012/11/08 PHP
PHP 登录记住密码实现思路
2013/05/07 PHP
php魔术方法与魔术变量、内置方法与内置变量的深入分析
2013/06/03 PHP
PHP Yii框架之表单验证规则大全
2015/11/16 PHP
php获取'/'传参的值简单方法
2017/07/13 PHP
Yii 2.0实现联表查询加搜索分页的方法示例
2017/08/02 PHP
如何实现JS函数的重载
2006/09/22 Javascript
javascript 在firebug调试时用console.log的方法
2012/05/10 Javascript
用js判断输入是否为中文的函数
2014/03/10 Javascript
javascript简单实现滑动菜单效果的方法
2015/07/27 Javascript
浅谈JSON.stringify()和JOSN.parse()方法的不同
2016/08/29 Javascript
Nodejs下DNS缓存问题浅析
2016/11/16 NodeJs
原生js实现打字动画游戏
2017/02/04 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
修改Nodejs内置的npm默认配置路径方法
2018/05/13 NodeJs
vue.js 双层嵌套for遍历的方法详解, 类似php foreach()
2018/09/07 Javascript
express+vue+mongodb+session 实现注册登录功能
2018/12/06 Javascript
nodejs nedb 封装库与使用方法示例
2020/02/06 NodeJs
vue-cli或vue项目利用HBuilder打包成移动端app操作
2020/07/29 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
2020/09/21 Javascript
[46:43]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第二局
2016/03/02 DOTA
Python Web开发模板引擎优缺点总结
2014/05/06 Python
python模拟enum枚举类型的方法小结
2015/04/30 Python
Python操作Sql Server 2008数据库的方法详解
2018/05/17 Python
简单了解python中对象的取反运算符
2019/07/01 Python
python rsa实现数据加密和解密、签名加密和验签功能
2019/09/18 Python
python运用sklearn实现KNN分类算法
2019/10/16 Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
2019/12/05 Python
Python 音频生成器的实现示例
2019/12/24 Python
详解python中的lambda与sorted函数
2020/09/04 Python
Kate Spade美国官网:纽约新兴时尚品牌,以包包闻名于世
2017/11/09 全球购物
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
大学生创业计划书
2014/08/14 职场文书
南京导游词
2015/02/03 职场文书
2016年八一建军节活动总结
2016/04/05 职场文书
Python如何加载模型并查看网络
2022/07/15 Python