apply 和 call 的区别

ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。

原文作者:林鑫,作者博客:https://github.com/lin-xin/blog

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 中 闭包 的详解。

更多文章:lin-xin/blog

转载于:https://www.cnblogs.com/linxin/p/6592664.html

JavaScript 中 apply 、call 的详解相关推荐

  1. JavaScript中DOM对象的详解

    *** JavaScript中DOM对象的详解*** DOM对象:Document Object Model,文档对象模型.也称为document(文档对象),是HTML页面当前窗体的内容,是连接JS ...

  2. php 实现setinterval,JavaScript中setInterval的使用详解

    相信很多大伙都知道JavaScript中setInterval的作用是在播放动画的时,每隔一定时间就调用函数,方法或对象,也有很多小伙伴对此也只是知道setInterval的定义.也是一知半解,今天我 ...

  3. Javascript中的Document对象详解

    Document对象详解 document 文挡对象 - JavaScript脚本语言描述           -------------------------------------------- ...

  4. javascript中的闭包closure详解

    文章目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一 ...

  5. JavaScript 中常见排序算法详解

    十大经典算法 一张图概括: 名词解释: n:数据规模 k:"桶"的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后2个相等键值 ...

  6. javascript 中match函数使用详解

    javascript中的match函数是使用正则表达式对字符串进行查找,并将查找的结果作为数组返回,在实际开发中非常的有用,使用方法如下: stringObj.match(rgExp) 其中strin ...

  7. JavaScript中的valueOf方法详解

    Object.prototype.valueOf() valueOf() 方法返回指定对象的原始值. 语法 object.valueOf() 返回值 返回值为该对象的原始值. 描述 JavaScrip ...

  8. JavaScript中的window对象详解

    1.window对象简介 (1)在JavaScript中,一个浏览器窗口就是一个window对象. (2)一个窗口就是一个window对象,这个窗口里面的HTML文档就是一个document对象,do ...

  9. 理解JavaScript中this的指向详解

    this的定义和理解: this是JavaScript语言的一个关键字,它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内使用. 1.this和执行环境对象有关,和函数的声明无关. var ...

  10. PHP和javascript中url编码解码详解

    在实际开发中,我们可能会遇到路径编码解码的问题,下面总结了一下: PHP中: 1.urlencode(编码),urldecode(解码) $a = urlencode('http://www.baid ...

最新文章

  1. Linux下硬盘安装linux
  2. 介绍一下 information_schema 库
  3. facade-pattern外观模式
  4. Day 02 第二天课时总结
  5. 向量空间 Vector Space -- 推荐系统
  6. 华大基因:新型冠状病毒检测试剂盒日均产能已达8万人份
  7. 北斗形变监测系统_一款基于北斗卫星定位边坡表面位移监测系统
  8. 计算机网络---DHCP/NAT(简单介绍)
  9. 信号之sleep函数
  10. BlackBerry HTML5 WebWorks 平台下,让BB10应用连接上BBM
  11. 精准验码,昂视助力锂电生产管理追溯
  12. android webview浏览器下载文件,Android 浏览器 —— 使用 WebView 实现文件下载
  13. java 静态方法中调用非静态方法
  14. 地球经纬度转换为unity球面坐标
  15. pyton 内置模块
  16. 如何对计算机进行磁盘整理,如何对Windows 7进行磁盘碎片整理?
  17. PHP民俗文化管理系统,中国民俗文化
  18. Netty ChannelGroup自动移除InActive的Channel实现
  19. 与chatGPT的第一次亲密接触
  20. opencv2/3播放视频实现进度条显示拖动、快进、快退、逐帧播放、显示当前帧于图像

热门文章

  1. sqlplus可以连接plsql连接不上_Gee引擎配置微端不更新,连接不上,尝试重新连接的解决方法...
  2. java中的关键字transient说明
  3. Window setTimeout() 方法
  4. JS将Date加八小时
  5. Java系统中如何拆分同步和异步
  6. AIoT催使AI深度场景化,“AI赋能,智联万物——开发者沙龙·南京站”圆满落幕...
  7. chrome fiddler 重定向 https 请求
  8. Django通过pycharm创建后,如何登录admin后台?
  9. AI 是中性的技术,如何用它更好地为人类服务
  10. 将Java项目从maven迁移到gradle