浅谈JavaScript中的apply,call和bind
apply,call,bine 这三兄弟经常让初学者感到疑惑。前两天准备面试时特地做了个比较,其实理解起来也不会太难。
apply
apply() 方法调用一个函数,指定该函数的 this 值并将一个数组(或类数组对象)作为该函数的参数。
语法 (Syntax)
fun.apply(thisArg,[argsArray])
直接上代码
function sayColor(arg) {
var color = "red";
console.log(arg + this.color);
}
var obj = {color: "blue"};
sayColor.apply(obj, ["The color is"]); //输出"The color is blue"
此时 this 指向 obj ,则 this.color 为 obj 的 color 属性,则输出 The color is blue。
call
call() 与 apply() 类似,区别在于 apply() 的第二个参数为数组,而 call() 把参数跟在第一个参数后面,并且可以跟多个参数。
语法 (Syntax)
fun.call(thisArg, arg1, arg2, arg3 ...)
看代码
function sayClothe(arg1,arg2) {
console.log(arg1 + this.color + arg2);
}
var obj = {color: "blue"};
sayClothe.call(obj, "This is a ", " clothe" ); //输出"This is a blue clothe"
bind
bind() 与 call() 类似,有一点不同在于 bind() 返回一个新函数(new function),我们可以随时调用该函数。
语法(Syntax)
fun.bind(thisArg, arg1, arg2, arg3 ...)
返回值
返回一个具有指定 this 和初始参数的函数副本。
看代码
function sayClothe(arg1, arg2) {
console.log(arg1 + this.color + arg2);
}
var obj = {color: "blue"};
var sayClothe2 = sayClothe.bind(obj, "This is a ", " clothe");
sayClothe2(); //输出 "This is a blue clothe"
使用
有时候我们会碰到 Array.prototype.slice.call(arguments) 这种用法。许多人会疑惑,直接使用 arguments.slice() 不就行了吗,为什么要多此一举。
原因在于,arguments 并不是真正的数组对象,只是 array-like object ,所以它并没有 slice 这个方法。而 Array.prototype.slice.call(arguments) 可以理解为把 slice 的对象指向 arguments ,从而让 arguments 可以使用 slice 方法。如果直接使用 arguments.slice() 则会报错。
bind() 的另一个用法则是让函数拥有预设参数,而又跟预设参数有所不同。
以下例子结合上面两条规则 本例出自MDN
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); //[1, 2, 3]
//Create a function with a preset leading arguments
var leadingThirtysevenList = list.bind(null, 37);
var list2 = leadingThirtysevenList();
//[37]
var list3 = leadingThirtysevenList(1, 2, 3);
//[37, 1, 2, 3]
我们想到预设参数就会理所当然的想到 “如果该函数没有参数就使用预设参数,有参数就使用提供的参数”。不过 bind() 所提供的预设参数功能与此不同。
在我们的印象中, list3 应该输出 [1, 2, 3] 但实际输出的却是 [37, 1, 2, 3]。因为 bind() 的特点,leadingThirtysevenList(1, 2, 3) 可以写为 list.bind(null, 37, 1, 2, 3)。
总结
apply() call() bind() 三者区别不大,都是用来改变函数的 this 指向。
apply() 把 this 所需参数放入一个数组,作为 apply() 的第二个参数传入。当参数不定时,我们可以传入 arguments。 call() 和 bind() 则把参数按顺序依次传入。
bind() 返回对应函数,便于稍后调用,而 apply()、call()则立即调用
由于其特性,使用起来千奇百怪,有各种各样有趣的用法,还等待我们去挖掘。
浅谈JavaScript中的apply,call和bind的更多相关文章
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈JavaScript中的null和undefined
浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈JavaScript中的继承
引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...
- 浅谈JavaScript中的内存管理
一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...
- 浅谈JavaScript中闭包
引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...
- 浅谈JavaScript中的Function引用类型
引言 在JavaScript中最有意思的就是函数了,这一切的根源在于函数实际上是一个对象.每一个函数都是Function类型的实例,而且都和其他引用类型的实例一样具有属性和方法.函数作为一个对象,因此 ...
- 浅谈JavaScript中的this
引言 JavaScript 是一种脚本语言,因此被很多人认为是简单易学的.然而情况恰恰相反,JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.本文仅采撷其中的一例:JavaScri ...
- 浅谈JavaScript中继承的实现
谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我 ...
随机推荐
- C# Redis分布式缓存
C# Redis实战(七) 七.修改数据 在上一篇 C# Redis实战(六)中介绍了如何查询Redis中数据,本篇将介绍如何修改Redis中相关数据.大家都知道Redis是key-value型存储系 ...
- 深入学习PHP内核
http://www.php-internals.com/ 深入学习PHP内核 http://www.php-internals.com/book/ http://www.kancloud.cn/@ ...
- 数据连接命令join
join主要用来将两个相关联的文件连接起来.两个文件相关联的意思是指这两个文件中有一些字段是关联的,例如两个文件的第1个字段都是学号,且每个学生的学号是唯一的.像这种具有唯一性关联的文件,就可以使用j ...
- opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰
认识着色器 理解OpenGL渲染管线,对于学习OpenGL非常重要.下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段) 此图是从wiki中拿过来的,OpenGL的渲染管线主要包括: ...
- ubuntu thrift 0.9.3编译安装
Table of Contents 1. 下载thrift源代码 2. 编译并安装 3. 运行测试程序 4. 安装 1 下载thrift源代码 git clone https://git-wip-us ...
- _IO, _IOR, _IOW, _IOWR 宏的用法与解析
转载:http://blog.chinaunix.net/uid-20754793-id-177774.html 今天在写字符驱动验证程序的时候要用到ioctl函数,其中有一个cmd参数,搞了半天也不 ...
- 关于android:inputType属性的说明
<EditText android:layout_width="fill_parent" android:layout_height="wrap_content&q ...
- 快递鸟物流单号自动识别接口JAVA对接demo
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...
- Cable master(二分题 注意精度)
Cable master Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26596 Accepted: 5673 Des ...
- cocos2dx3.0-tinyxml在Android环境下解析xml失败的问题
本文由@呆代待殆原创,转载请注明出处. 正常情况下,我们在用tinyxml读取xml文件的的时候,会像下面这样写. std::string filePath = FileUtils::getInsta ...