JavaScript 中 apply 、call 的详解


Posted in Javascript onMarch 21, 2017

apply 和 call 的区别

ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。

apply( )

apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。

var obj = {
 name : 'linxin'
}
function func(firstName, lastName){
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); // A linxin B

可以看到,obj 是作为函数上下文的对象,函数 func 中 this 指向了 obj 这个对象。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。

call( )

call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。

var obj = {
 name: 'linxin'
}
function func(firstName, lastName) {
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D');  // C linxin D

对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中。

对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。

apply 和 call 的用法

1.改变 this 指向

var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
func.call(obj);  // linxin

我们知道,call 方法的第一个参数是作为函数上下文的对象,这里把 obj 作为参数传给了 func,此时函数里的 this 便指向了 obj 对象。此处 func 函数里其实相当于

function func() {
 console.log(obj.name);
}

2.借用别的对象的方法

先看例子

var Person1 = function () {
 this.name = 'linxin';
}
var Person2 = function () {
 this.getname = function () {
  console.log(this.name);
 }
 Person1.call(this);
}
var person = new Person2();
person.getname();  // linxin

从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

3.调用函数

apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。

function func() {
 console.log('linxin');
}
func.call();   // linxin

call 和 bind 的区别

在 EcmaScript5 中扩展了叫 bind 的方法,在低版本的 IE 中不兼容。它和 call 很相似,接受的参数有两部分,第一个参数是是作为函数上下文的对象,第二部分参数是个列表,可以接受多个参数。

它们之间的区别有以下两点。

1.bind 发返回值是函数

var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
var func1 = func.bind(obj);
func1();      // linxin

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 func 中的 this 并没有被改变,依旧指向全局对象 window。

2.参数的使用

function func(a, b, c) {
 console.log(a, b, c);
}
var func1 = func.bind(null,'linxin');
func('A', 'B', 'C');   // A B C
func1('A', 'B', 'C');   // linxin A B
func1('B', 'C');    // linxin B C
func.call(null, 'linxin');  // linxin undefined undefined

call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。

在低版本浏览器没有 bind 方法,我们也可以自己实现一个。

if (!Function.prototype.bind) {
 Function.prototype.bind = function () {
  var self = this,      // 保存原函数
   context = [].shift.call(arguments), // 保存需要绑定的this上下文
   args = [].slice.call(arguments); // 剩余的参数转为数组
  return function () {     // 返回一个新函数
   self.apply(context,[].concat.call(args, [].slice.call(arguments)));
  }
 }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
JQuery 选择器 xpath 语法应用
May 13 Javascript
JavaScript用Number方法实现string转int
May 13 Javascript
直接在JS里创建JSON数据然后遍历使用
Jul 25 Javascript
javascript实现将文件保存到本地方法汇总
Jul 26 Javascript
JQUERY表单暂存功能插件分享
Feb 23 Javascript
jQuery实现内容定时切换效果完整实例
Apr 06 Javascript
使用Angular缓存父页面数据的方法
Jan 03 Javascript
纯js实现html转pdf的简单实例(推荐)
Feb 16 Javascript
基于vue的fullpage.js单页滚动插件
Mar 20 Javascript
JavaScript变量声明var,let.const及区别浅析
Apr 23 Javascript
原生javascript运动函数的封装示例【匀速、抛物线、多属性的运动等】
Feb 23 Javascript
js事件机制----捕获与冒泡机制实例分析
May 22 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 #Javascript
Bootstrap警告框(Alert)插件使用方法
Mar 21 #Javascript
Bootstrap标签页(Tab)插件使用方法
Mar 21 #Javascript
JavaScript数组和对象的复制
Mar 21 #Javascript
Vue响应式添加、修改数组和对象的值
Mar 20 #Javascript
zTree实现节点修改的实时刷新功能
Mar 20 #Javascript
Vue指令的钩子函数使用方法
Mar 20 #Javascript
You might like
php在服务器执行exec命令失败的解决方法
2012/03/03 PHP
php判断两个日期之间相差多少个月份的方法
2015/06/18 PHP
PHP扩展Memcache分布式部署方案
2015/12/06 PHP
PHP命名空间namespace的定义方法详解
2017/03/29 PHP
Laravel框架源码解析之入口文件原理分析
2020/05/14 PHP
Mootools 1.2教程 同时进行多个形变动画
2009/09/15 Javascript
用JS写的一个TableView控件代码
2010/01/23 Javascript
js时间比较示例分享(日期比较)
2014/03/05 Javascript
js转化毫秒为时间格式代码
2014/04/10 Javascript
浅谈JavaScript实现面向对象中的类
2014/12/09 Javascript
jquery 插件实现瀑布流图片展示实例
2015/04/03 Javascript
javascript实现支持移动设备画廊
2015/08/24 Javascript
js如何判断访问是来自搜索引擎(蜘蛛人)还是直接访问
2015/09/14 Javascript
详解JavaScript数组和字符串中去除重复值的方法
2016/03/07 Javascript
NodeJS遍历文件生产文件列表功能示例
2017/01/22 NodeJs
从零开始学习Node.js系列教程一:http get和post用法分析
2017/04/13 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
在vue中获取wangeditor的html和text的操作
2020/10/23 Javascript
[01:06:32]DOTA2上海特级锦标赛D组资格赛#1 EG VS VP第一局
2016/02/28 DOTA
python 示例分享---逻辑推理编程解决八皇后
2014/07/20 Python
Python 3.x 新特性及10大变化
2015/06/12 Python
python使用adbapi实现MySQL数据库的异步存储
2019/03/19 Python
从列表或字典创建Pandas的DataFrame对象的方法
2019/07/06 Python
Python3实现配置文件差异对比脚本
2019/11/18 Python
Python sorted对list和dict排序
2020/06/09 Python
python与idea的集成的实现
2020/11/20 Python
socket.io 和canvas 实现的共享画板功能
2019/05/22 HTML / CSS
世界领先的艺术图书出版社:TASCHEN
2018/07/23 全球购物
Bibloo荷兰:女士、男士和儿童的服装、鞋子和配饰
2019/02/25 全球购物
Bluebella法国官网:英国性感内衣品牌
2019/05/03 全球购物
Liu Jo西班牙官网:意大利服装品牌
2019/09/11 全球购物
双立人美国官方商店:ZWILLING集团餐具和炊具
2020/05/07 全球购物
怎样客观的做好自我评价
2013/12/28 职场文书
区三好学生主要事迹
2014/01/30 职场文书
乡镇信息公开实施方案
2014/03/23 职场文书
校园广播稿范文
2015/08/19 职场文书