玩转方法: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 相关文章推荐
JavaScript 给汉字排序实例代码
Jun 28 Javascript
GRID拖拽行的实例代码
Jul 18 Javascript
从QQ网站中提取的纯JS省市区三级联动菜单
Dec 25 Javascript
jQuery实现的简单提示信息插件
Dec 08 Javascript
JavaScript判断表单为空及获取焦点的方法
Feb 12 Javascript
总结JavaScript设计模式编程中的享元模式使用
May 21 Javascript
javascript简单进制转换实现方法
Nov 24 Javascript
node+koa实现数据mock接口的方法
Sep 20 Javascript
微信小程序有旋转动画效果的音乐组件实例代码
Aug 22 Javascript
使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)
Oct 23 Javascript
vue中的mescroll搜索运用及各种填坑处理
Oct 30 Javascript
Vue简单实现原理详解
May 07 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
DC动漫人物排行
2020/03/03 欧美动漫
php 结果集的分页实现代码
2009/03/10 PHP
php面向对象全攻略 (十四) php5接口技术
2009/09/30 PHP
PHP使用memcache缓存技术提高响应速度的方法
2014/12/26 PHP
PHP按指定键值对二维数组进行排序的方法
2015/12/22 PHP
PHP中有关长整数的一些操作教程
2019/09/11 PHP
laravel利用中间件防止未登录用户直接访问后台的方法
2019/09/30 PHP
PHP Swoole异步MySQL客户端实现方法示例
2019/10/24 PHP
JavaScript入门教程(6) Window窗口对象
2009/01/31 Javascript
JQuery切换显示的效果实例代码
2013/02/27 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
用jquery实现动画跳到顶部和底部(这个比较简单)
2014/09/01 Javascript
jQuery实现新消息在网页标题闪烁提示
2015/06/23 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
2015/10/16 Javascript
基于JavaScript代码实现随机漂浮图片广告
2016/01/05 Javascript
微信公众平台开发教程(四) 实例入门:机器人回复(附源码)
2016/12/02 Javascript
使用JS 插件qrcode.js生成二维码功能
2017/02/20 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
vue完成项目后,打包成静态文件的方法
2018/09/03 Javascript
微信小程序前端promise封装代码实例
2019/08/24 Javascript
vue实现购物车小案例
2019/09/27 Javascript
JS实现可视化音频效果的实例代码
2020/01/16 Javascript
js函数柯里化的方法和作用实例分析
2020/04/11 Javascript
python 解决print数组/矩阵无法完整输出的问题
2020/02/19 Python
Django rest framework分页接口实现原理解析
2020/08/21 Python
python自动从arxiv下载paper的示例代码
2020/12/05 Python
约瑟夫·特纳男装:Joseph Turner
2017/10/10 全球购物
锐步香港官方网上商店:Reebok香港
2020/11/05 全球购物
销售冠军获奖感言
2014/02/03 职场文书
不打扫卫生检讨书
2014/02/12 职场文书
国王的演讲观后感
2015/06/03 职场文书
公司开业主持词
2015/07/02 职场文书
2016优秀大学生个人事迹材料范文
2016/03/01 职场文书
辞职信怎么写?你都知道吗?
2019/06/24 职场文书
2019年家电促销广告语集锦
2019/10/21 职场文书
Python中tkinter的用户登录管理的实现
2021/04/22 Python