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 OOP类与继承
Nov 15 Javascript
Safari5中alert的无限循环BUG
Apr 07 Javascript
Jquery 的扩展方法总结
Oct 01 Javascript
js常用代码段整理
Nov 30 Javascript
jquery删除指定的html标签并保留标签内文本内容的方法
Apr 02 Javascript
用jquery实现动画跳到顶部和底部(这个比较简单)
Sep 01 Javascript
jquery简单实现网页层的展开与收缩效果
Aug 07 Javascript
javascript实现禁止复制网页内容汇总
Dec 30 Javascript
jQuery Ajax 实现在html页面实时显示用户登录状态
Dec 30 Javascript
如何在Angular应用中创建包含组件方法示例
Mar 23 Javascript
vue中用 async/await 来处理异步操作
Jul 18 Javascript
用JS写一个发布订阅模式
Nov 07 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代码
2012/09/14 PHP
ThinkPHP之A方法实例讲解
2014/06/20 PHP
PHP上传文件时自动分配路径的方法
2015/01/09 PHP
php实现过滤字符串中的中文和数字实例
2015/07/29 PHP
PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)
2020/08/03 PHP
jQuery对表单的操作代码集合
2011/04/06 Javascript
ASP.NET jQuery 实例10 动态修改hyperlink的URL值
2012/02/03 Javascript
html a标签-超链接中confirm方法使用介绍
2013/01/04 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
js关于字符长度限制的问题示例探讨
2014/01/24 Javascript
javascript模拟枚举的简单实例
2014/03/06 Javascript
JavaScript小技巧整理
2015/12/30 Javascript
最好用的Bootstrap fileinput.js文件上传组件
2016/12/12 Javascript
Vue.js手风琴菜单组件开发实例
2017/05/16 Javascript
微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】
2017/12/06 Javascript
iview日期控件,双向绑定日期格式的方法
2018/03/15 Javascript
基于element-ui封装可搜索的懒加载tree组件的实现
2020/05/22 Javascript
解决idea开发遇到javascript动态添加html元素时中文乱码的问题
2020/09/29 Javascript
[46:44]VG vs TNC Supermajor小组赛B组败者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
Python中实现对Timestamp和Datetime及UTC时间之间的转换
2015/04/08 Python
python实现简单socket通信的方法
2016/04/19 Python
Python基于回溯法子集树模板实现8皇后问题
2017/09/01 Python
Python图像处理PIL各模块详细介绍(推荐)
2019/07/17 Python
Python递归调用实现数字累加的代码
2020/02/25 Python
python模拟斗地主发牌
2020/04/22 Python
资产评估专业学生的自我鉴定
2013/11/14 职场文书
施工班组长岗位职责
2014/01/05 职场文书
乐观大学生的自我评价
2014/01/10 职场文书
市场营销个人求职信范文
2014/02/02 职场文书
计算机专业应届生求职信
2014/04/06 职场文书
学校安全责任书
2014/04/14 职场文书
关于安全的广播稿
2014/10/23 职场文书
2015初中教导处工作总结
2015/07/21 职场文书
酒店厨房管理制度
2015/08/06 职场文书
爱护公物主题班会
2015/08/17 职场文书
HTML5简单实现添加背景音乐的几种方法
2021/05/12 HTML / CSS