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 中文字符串处理额外注意事项
Nov 15 Javascript
js constructor的实际作用分析
Nov 15 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
Oct 11 Javascript
JS:window.onload的使用介绍
Nov 13 Javascript
jQuery性能优化的38个建议
Mar 04 Javascript
AngularJs根据访问的页面动态加载Controller的解决方案
Feb 04 Javascript
基于JS判断iframe是否加载成功的方法(多种浏览器)
May 13 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
Jun 13 Javascript
利用Javascript实现BMI计算器
Aug 16 Javascript
js实现首屏延迟加载实现方法 js实现多屏单张图片延迟加载效果
Jul 17 Javascript
jQuery实现键盘回车搜索功能
Jul 25 jQuery
express 项目分层实践详解
Dec 10 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 a simple smtp class
2007/11/26 PHP
Ajax PHP简单入门教程代码
2008/04/25 PHP
让Json更懂中文(JSON_UNESCAPED_UNICODE)
2011/10/27 PHP
10款PHP开源商城系统汇总介绍
2015/07/23 PHP
学习php设计模式 php实现适配器模式
2015/12/07 PHP
详解json在php中的应用
2018/09/30 PHP
PHP实现递归的三种方法
2020/07/04 PHP
符合标准的js表单提交的代码
2007/09/13 Javascript
JavaScript常用对象的方法和属性小结
2012/01/24 Javascript
JQuery伸缩导航练习示例
2013/11/13 Javascript
JS控制一个DIV层在指定时间内消失的方法
2014/02/17 Javascript
基于HTML5+JS实现本地图片裁剪并上传功能
2017/03/24 Javascript
Node.js 多进程处理CPU密集任务的实现
2019/05/26 Javascript
Vue中实现回车键切换焦点的方法
2020/02/19 Javascript
python基础教程之实现石头剪刀布游戏示例
2014/02/11 Python
Python中的True,False条件判断实例分析
2015/01/12 Python
用Pygal绘制直方图代码示例
2017/12/07 Python
人生苦短我用python python如何快速入门?
2018/03/12 Python
python 3.6.4 安装配置方法图文教程
2018/09/18 Python
python 多线程重启方法
2019/02/18 Python
python烟花效果的代码实例
2020/02/25 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
2020/02/28 Python
css3 transform 3d 使用css3创建动态3d立方体(html5实践)
2013/01/06 HTML / CSS
英国汽车和货车租赁网站:Hertz英国
2016/09/02 全球购物
中药专业毕业自荐书范文
2014/02/08 职场文书
主管会计岗位责任制
2014/02/10 职场文书
远程网络教育毕业生自我鉴定
2014/04/14 职场文书
我的中国梦演讲稿初中篇
2014/08/19 职场文书
购房协议书范本(无房产证)
2014/10/07 职场文书
学校党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
美术教师求职信范文
2015/03/20 职场文书
2019年大学推荐信
2019/06/24 职场文书
担保书范文
2019/07/09 职场文书
基于Nginx实现限制某IP短时间访问次数
2021/03/31 Servers
MySQL系列之三 基础篇
2021/07/02 MySQL
Go语言空白表示符_的实例用法
2021/07/04 Golang