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 相关文章推荐
自己开发Dojo的建议框架
Sep 24 Javascript
IE6不能修改NAME问题的解决方法
Sep 03 Javascript
jquery中对于批量deferred的处理方法
Jan 22 Javascript
jQuery拖动布局其结果保存到数据库
Oct 09 Javascript
JavaScript识别网页关键字并进行描红的方法
Nov 09 Javascript
jQuery EasyUI Tab 选项卡问题小结
Aug 16 Javascript
JavaScript对象创建模式实例汇总
Oct 03 Javascript
基本DOM节点操作
Jan 17 Javascript
ES6正则的扩展实例详解
Apr 25 Javascript
web页面和微信小程序页面实现瀑布流效果
Sep 26 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
Jun 17 Javascript
Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作
Aug 31 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统计数值数组中出现频率最多的10个数字的方法
2015/04/20 PHP
php实现微信模拟登陆、获取用户列表及群发消息功能示例
2017/06/28 PHP
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
模拟一个类似百度google的模糊搜索下拉列表
2014/04/15 Javascript
ExtJS4 表格的嵌套 rowExpander应用
2014/05/02 Javascript
js实现匹配时换色的输入提示特效代码
2015/08/17 Javascript
JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
2016/05/16 Javascript
利用JS判断鼠标移入元素的方向
2016/12/11 Javascript
js中的DOM模拟购物车功能
2017/03/22 Javascript
Javascript 详解封装from表单数据为json串进行ajax提交
2017/03/29 Javascript
解决vue项目中type=”file“ change事件只执行一次的问题
2018/05/16 Javascript
微信小程序和百度的语音识别接口详解
2019/05/06 Javascript
vue中实现Monaco Editor自定义提示功能
2019/07/05 Javascript
jQuery实现的分页插件完整示例
2020/05/26 jQuery
Python中类的继承代码实例
2014/10/28 Python
Python numpy 常用函数总结
2017/12/07 Python
python指定写入文件时的编码格式方法
2018/06/07 Python
Python去除字符串前后空格的几种方法
2019/03/04 Python
Django import export实现数据库导入导出方式
2020/04/03 Python
ansible-playbook实现自动部署KVM及安装python3的详细教程
2020/05/11 Python
Python3批量创建Crowd用户并分配组
2020/05/20 Python
Python 中Operator模块的使用
2021/01/30 Python
CSS3中box-shadow的用法介绍
2015/07/15 HTML / CSS
纯CSS3单页切换导航菜单界面设计的简单实现
2016/08/16 HTML / CSS
H5仿微信界面教程(一)
2017/07/05 HTML / CSS
Fanatics法国官网:美国体育电商
2019/08/27 全球购物
莫斯科制造商的廉价皮大衣:Fursk
2020/06/09 全球购物
军校大学生个人的自我评价
2014/02/17 职场文书
信息科学与技术专业求职信范文
2014/02/20 职场文书
2014年大学生四年规划书范文
2014/04/03 职场文书
应届毕业生求职信范文
2014/05/08 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
2016年“我们的节日·端午节”活动总结
2016/04/01 职场文书
一文搞清楚MySQL count(*)、count(1)、count(col)区别
2022/03/03 MySQL
Python实现批量自动整理文件
2022/03/16 Python
Win11如何启用启动修复 ? Win11执行启动修复的三种方法
2022/04/08 数码科技