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伸缩导航练习示例
Nov 13 Javascript
jquery操作cookie插件分享
Jan 14 Javascript
seajs中模块的解析规则详解和模块使用总结
Mar 12 Javascript
node.js Web应用框架Express入门指南
May 28 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
Sep 22 Javascript
jQuery表单验证插件解析(推荐)
Jul 21 Javascript
详解Vuejs2.0 如何利用proxyTable实现跨域请求
Aug 03 Javascript
vue中组件的过渡动画及实现代码
Nov 21 Javascript
bootstrap中的导航条实例代码详解
May 20 Javascript
jquery实现两个div中的元素相互拖动的方法分析
Apr 05 jQuery
Ajax获取node服务器数据的完整步骤
Sep 20 Javascript
浅谈JavaScript作用域
Dec 06 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字符串函数学习之substr()
2015/03/27 PHP
PHP变量赋值、代入给JavaScript中的变量
2015/06/29 PHP
thinkPHP js文件中U方法不被解析问题的解决方法
2016/12/05 PHP
php+jQuery实现的三级导航栏下拉菜单显示效果
2017/08/10 PHP
PHP convert_uudecode()函数讲解
2019/02/14 PHP
PHP查找一列有序数组是否包含某值的方法
2020/02/07 PHP
PHP如何通过带尾指针的链表实现'队列'
2020/10/22 PHP
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
2011/01/17 Javascript
Extjs gridpanel 出现横向滚动条问题的解决方法
2011/07/04 Javascript
页面定时刷新(1秒刷新一次)
2013/11/22 Javascript
JavaScript判断浏览器类型的方法
2015/02/10 Javascript
学习JavaScript设计模式(单例模式)
2015/11/26 Javascript
JavaScript暂停和继续定时器的实现方法
2016/07/18 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
JavaScript之map reduce_动力节点Java学院整理
2017/06/29 Javascript
解决linux下node.js全局模块找不到的问题
2018/05/15 Javascript
[jQuery] 事件和动画详解
2019/03/05 jQuery
ionic3双击返回退出应用的方法
2019/09/17 Javascript
jquery实现两个div中的元素相互拖动的方法分析
2020/04/05 jQuery
js闭包和垃圾回收机制示例详解
2021/03/01 Javascript
python分割列表(list)的方法示例
2017/05/07 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
Python标准库inspect的具体使用方法
2017/12/06 Python
Python实现带参数与不带参数的多重继承示例
2018/01/30 Python
python获取代码运行时间的实例代码
2018/06/11 Python
Django实现内容缓存实例方法
2020/06/30 Python
利用CSS3制作简单的3d半透明立方体图片展示
2017/03/25 HTML / CSS
荷兰在线啤酒店:Beerwulf
2019/08/26 全球购物
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
Kendra Scott官网:美国领先的时尚配饰品牌
2020/10/22 全球购物
幼儿园安全责任书范本
2014/07/24 职场文书
学习党代会心得体会
2014/09/05 职场文书
房屋出售授权委托书
2014/10/12 职场文书
大学校园招聘会感想
2015/08/10 职场文书
文书工作总结(范文)
2019/07/11 职场文书
Nginx开源可视化配置工具NginxConfig使用教程
2022/06/21 Servers