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 相关文章推荐
幻宇的层模拟窗口效果-提供演示和下载
Jan 20 Javascript
鼠标经过出现气泡框的简单实例
Mar 17 Javascript
基于bootstrap按钮式下拉菜单组件的搜索建议插件
Mar 25 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
Apr 03 jQuery
基于Jquery Ajax type的4种类型(详解)
Aug 02 jQuery
vue.js默认路由不加载linkActiveClass问题的解决方法
Dec 11 Javascript
用JS实现根据当前时间随机生成流水号或者订单号
May 31 Javascript
微信小程序--特定区域滚动到顶部时固定的方法
Apr 28 Javascript
解决vue单页面修改样式无法覆盖问题
Aug 05 Javascript
vue实现移动端触屏拖拽功能
Aug 21 Javascript
Vue $attrs & inheritAttr实现button禁用效果案例
Dec 07 Vue.js
AJAX引擎原理以及XmlHttpRequest对象的axios、fetch区别详解
Apr 09 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 Curl出现403错误的解决办法
2014/05/29 PHP
让codeigniter与swfupload整合的最佳解决方案
2014/06/12 PHP
PHP限制HTML内容中图片必须是本站的方法
2015/06/16 PHP
ThinkPHP里用U方法调用js文件实例
2015/06/18 PHP
php弹出提示框的是实例写法
2019/09/26 PHP
HTA版JSMin(省略修饰语若干)基于javascript语言编写
2009/12/24 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
2013/10/25 Javascript
js实现右下角提示框的方法
2015/02/03 Javascript
浅谈angularJS 作用域
2015/07/05 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
2016/04/01 Javascript
极力推荐一款小巧玲珑的可视化编辑器bootstrap-wysiwyg
2016/05/27 Javascript
jQuery UI结合Ajax创建可定制的Web界面
2016/06/22 Javascript
vue中rem的配置的方法示例
2018/08/30 Javascript
js+canvas实现简单扫雷小游戏
2021/01/22 Javascript
js实现经典贪吃蛇小游戏
2020/03/19 Javascript
Javascript 模拟mvc实现点餐程序案例详解
2020/12/24 Javascript
在Python下进行UDP网络编程的教程
2015/04/29 Python
Python定义函数功能与用法实例详解
2019/04/08 Python
Python OpenCV调用摄像头检测人脸并截图
2020/08/20 Python
Python 读取用户指令和格式化打印实现解析
2019/09/02 Python
Python+OpenCV图像处理——实现轮廓发现
2020/10/23 Python
土耳其时尚潮流在线购物网站:Trendyol
2017/10/10 全球购物
少先队入队活动方案
2014/02/08 职场文书
楼面经理岗位职责范本
2014/02/18 职场文书
会计学自荐信
2014/06/03 职场文书
法学专业毕业生自荐信
2014/06/11 职场文书
青岛海底世界导游词
2015/02/11 职场文书
党校团干班培训心得体会
2016/01/06 职场文书
2016年教师党员创先争优承诺书
2016/03/24 职场文书
详解Redis基本命令与使用场景
2021/06/01 Redis
使用numpy实现矩阵的翻转(flip)与旋转
2021/06/03 Python
React如何创建组件
2021/06/27 Javascript
vue elementUI表格控制对应列
2022/04/13 Vue.js
MySQL池化框架学习接池自定义
2022/07/23 MySQL
Python创建SQL数据库流程逐步讲解
2022/09/23 Python
华为HarmonyOS3.0强在哪? 看看鸿蒙3.0这7个小功能
2023/01/09 数码科技