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 相关文章推荐
JavaScript语句可以不以;结尾的烦恼
Mar 08 Javascript
JavaScript 事件对象的实现
Jul 13 Javascript
jQuery 数据缓存data(name, value)详解及实现
Jan 04 Javascript
ExtJS 入门
Oct 29 Javascript
学习从实践开始之jQuery插件开发 对话框插件开发
Apr 26 Javascript
html文件中jquery与velocity变量中的$冲突的解决方法
Nov 01 Javascript
jquery实现的伪分页效果代码
Oct 29 Javascript
js简单设置与使用cookie的方法
Jan 22 Javascript
jQuery模仿阿里云购买服务器选择购买时间长度的代码
Apr 29 Javascript
layer.prompt使文本框为空的情况下也能点击确定的方法
Sep 24 Javascript
Vuex的API文档说明详解
Feb 05 Javascript
详解前端任务构建利器Gulp.js使用指南
Apr 30 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 APC缓存配置、使用详解
2014/03/06 PHP
在laravel中使用Symfony的Crawler组件分析HTML
2017/06/19 PHP
非常不错的功能强大代码简单的管理菜单美化版
2008/07/09 Javascript
js汉字转拼音实现代码
2013/02/06 Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
2013/06/27 Javascript
vue自定义指令实现v-tap插件
2016/11/03 Javascript
JavaScript标准对象_动力节点Java学院整理
2017/06/27 Javascript
微信小程序iBeacon测距及稳定程序的实现解析
2019/07/31 Javascript
详解Nuxt.js中使用Element-UI填坑
2019/09/06 Javascript
vue resource发送请求的几种方式
2019/09/30 Javascript
JS实现排行榜文字向上滚动轮播效果
2019/11/26 Javascript
小程序自定义模板实现吸顶功能
2020/01/08 Javascript
JS写滑稽笑脸运动效果
2020/05/28 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
2020/07/22 Javascript
[45:25]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
Python编码时应该注意的几个情况
2013/03/04 Python
分析在Python中何种情况下需要使用断言
2015/04/01 Python
基于wxpython开发的简单gui计算器实例
2015/05/30 Python
使用Python的Flask框架构建大型Web应用程序的结构示例
2016/06/04 Python
Python文件夹与文件的相关操作(推荐)
2016/07/25 Python
python与C互相调用的方法详解
2017/07/14 Python
python2 与python3的print区别小结
2018/01/16 Python
Python3监控疫情的完整代码
2020/02/20 Python
Python自动化操作实现图例绘制
2020/07/09 Python
Html5实现如何在两个div元素之间拖放图像
2013/03/29 HTML / CSS
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
aden + anais英国官网:美国婴儿贴身用品品牌
2019/09/08 全球购物
Stokke美国官方网店:高级儿童家具、推车、汽车座椅和配件
2020/06/06 全球购物
大学校庆邀请函
2014/01/11 职场文书
《胡杨》教学反思
2014/02/16 职场文书
绿色环保家庭事迹材料
2014/08/31 职场文书
财务科长个人对照检查材料
2014/09/18 职场文书
2014年学校德育工作总结
2014/12/05 职场文书
2014小学二年级班主任工作总结
2014/12/05 职场文书
2016年小学生清明节广播稿
2015/12/17 职场文书
java泛型通配符详解
2021/07/25 Java/Android