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 三种不同位置代码的写法
Oct 25 Javascript
js或css文件后面跟参数的原因说明
Jan 09 Javascript
基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码
Aug 28 Javascript
网页打开自动最大化的js代码
Aug 22 Javascript
javascript 循环调用示例介绍
Nov 20 Javascript
Extjs表单常见验证小结
Mar 07 Javascript
director.js实现前端路由使用实例
Feb 03 Javascript
javascript通过元素id和name直接取得元素的方法
Apr 28 Javascript
简述JavaScript的正则表达式中test()方法的使用
Jun 16 Javascript
深入学习js瀑布流布局
Oct 14 Javascript
JavaScript、C# URL编码、解码总结
Jan 21 Javascript
JavaScript实现的搜索及高亮显示功能示例
Aug 14 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
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
PHP树的代码,可以嵌套任意层
2006/10/09 PHP
php格式化工具Beautify PHP小小BUG
2008/04/24 PHP
PHP三元运算符的结合性介绍
2012/01/10 PHP
深入理解php的MySQL连接类
2013/06/07 PHP
PHP批量检测并去除文件BOM头代码实例
2014/05/08 PHP
ThinkPHP中Common/common.php文件常用函数功能分析
2016/05/20 PHP
Jquery ui css framework
2010/06/28 Javascript
jquery $.ajax各个事件执行顺序
2010/10/15 Javascript
jQuery下通过$.browser来判断浏览器.
2011/04/05 Javascript
AngularJS中的包含详细介绍及实现示例
2016/07/28 Javascript
JS中判断null的方法分析
2016/11/21 Javascript
滚动条的监听与内容随着滚动条动态加载的实现
2017/02/08 Javascript
Vue2单一事件管理组件通信
2017/05/09 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)
2018/05/16 Javascript
使用Angular 6创建各种动画效果的方法
2018/10/10 Javascript
详细教你微信公众号正文页SVG交互开发技巧
2019/07/25 Javascript
深入理解令牌认证机制(token)
2019/08/22 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
2019/08/23 Javascript
layui 对table中的数据进行转义的实例
2019/09/12 Javascript
vue封装swiper代码实例解析
2019/10/08 Javascript
Js数组扁平化实现方法代码总汇
2020/11/11 Javascript
[51:26]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#3Secret VS OG第二局
2016/03/03 DOTA
python 循环遍历字典元素的简单方法
2016/09/11 Python
matplotlib简介,安装和简单实例代码
2017/12/26 Python
浅谈Python 列表字典赋值的陷阱
2019/01/20 Python
Python理解递归的方法总结
2019/01/28 Python
HTML5新特性之语义化标签
2017/10/31 HTML / CSS
森林防火工作方案
2014/02/14 职场文书
《美丽的彩虹》教学反思
2014/02/25 职场文书
教师考察材料范文
2014/06/03 职场文书
拾金不昧表扬信怎么写
2015/05/04 职场文书
python实现语音常用度量方法的代码详解
2021/05/25 Python
mysql5.7的安装及Navicate长久免费使用的实现过程
2021/11/17 MySQL
python绘制简单直方图(质量分布图)的方法
2022/04/21 Python