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 相关文章推荐
ImageFlow可鼠标控制图片滚动
Jan 30 Javascript
基于jQuery的js分页代码
Jun 10 Javascript
jQuery操作select下拉框的text值和value值的方法
May 31 Javascript
封装了jQuery的Ajax请求全局配置
Feb 05 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
Mar 02 Javascript
jQuery中 attr() 方法使用小结
May 03 Javascript
常用原生JS兼容性写法汇总
Apr 27 Javascript
bootstrap的3级菜单样式,支持母版页保留打开状态实现方法
Nov 10 Javascript
AngularJS 应用模块化的使用
Apr 04 Javascript
使用vue-cli导入Element UI组件的方法
May 16 Javascript
js实现移动端轮播图
Dec 21 Javascript
vue3实现v-model原理详解
Oct 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边学边教》(01.开篇――准备工作)
2006/12/13 PHP
php简单的会话类代码
2011/08/08 PHP
php另类上传图片的方法(PHP用Socket上传图片)
2013/10/30 PHP
php读取3389的脚本
2014/05/06 PHP
php实现复制移动文件的方法
2015/07/29 PHP
在textarea文本域中显示HTML代码的方法
2007/03/06 Javascript
你必须知道的Javascript知识点之"深入理解作用域链"的介绍
2013/04/23 Javascript
jquery限定文本框只能输入数字(整数和小数)
2016/01/08 Javascript
Angularjs material 实现搜索框功能
2016/03/08 Javascript
详解windows下vue-cli及webpack 构建网站(三)使用组件
2017/06/17 Javascript
实现单层json按照key字母顺序排序的示例
2017/12/06 Javascript
浅谈React + Webpack 构建打包优化
2018/01/23 Javascript
基于layui数据表格以及传数据的方式
2018/08/19 Javascript
微信小程序开发之路由切换页面重定向问题
2018/09/18 Javascript
解决在layer.open中使用时间控件laydate失败的问题
2019/09/11 Javascript
小程序自动化测试的示例代码
2020/08/11 Javascript
JS highcharts动态柱状图原理及实现
2020/10/16 Javascript
[03:00]2014DOTA2国际邀请赛 Titan淘汰潸然泪下Ohaiyo专访
2014/07/15 DOTA
[01:07:47]Secret vs Optic Supermajor 胜者组 BO3 第一场 6.4
2018/06/05 DOTA
使用python语言,比较两个字符串是否相同的实例
2018/06/29 Python
了解不常见但是实用的Python技巧
2019/05/23 Python
人工神经网络算法知识点总结
2019/06/11 Python
Python Pandas对缺失值的处理方法
2019/09/27 Python
浅谈Django中的QueryDict元素为数组的坑
2020/03/31 Python
PyPDF2读取PDF文件内容保存到本地TXT实例
2020/05/12 Python
Node.js 和 Python之间该选择哪个?
2020/08/05 Python
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
澳大利亚最超值的自行车之家:Reid Cycles
2019/03/24 全球购物
如何利用cmp命令比较文件
2016/04/11 面试题
汽车工程专业应届生求职信
2013/10/19 职场文书
行政副总岗位职责
2014/02/23 职场文书
质量月活动策划方案
2014/03/10 职场文书
初中英语演讲稿
2014/04/29 职场文书
求职信标题怎么写
2014/05/26 职场文书
设备售后服务承诺书
2014/05/30 职场文书
小学毕业典礼演讲稿
2014/09/09 职场文书