apply,call,bine 这三兄弟经常让初学者感到疑惑。前两天准备面试时特地做了个比较,其实理解起来也不会太难。

apply

MDN上的定义:

The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object).

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.colorobjcolor 属性,则输出 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() 的第二个参数传入。当参数不定时,我们可以传入 argumentscall()bind() 则把参数按顺序依次传入。

bind() 返回对应函数,便于稍后调用,而 apply()call()则立即调用

由于其特性,使用起来千奇百怪,有各种各样有趣的用法,还等待我们去挖掘。

浅谈JavaScript中的apply,call和bind的更多相关文章

  1. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  2. 浅谈JavaScript中的null和undefined

    浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...

  3. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

  4. 浅谈JavaScript中的继承

    引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...

  5. 浅谈JavaScript中的内存管理

    一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...

  6. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

  7. 浅谈JavaScript中的Function引用类型

    引言 在JavaScript中最有意思的就是函数了,这一切的根源在于函数实际上是一个对象.每一个函数都是Function类型的实例,而且都和其他引用类型的实例一样具有属性和方法.函数作为一个对象,因此 ...

  8. 浅谈JavaScript中的this

    引言 JavaScript 是一种脚本语言,因此被很多人认为是简单易学的.然而情况恰恰相反,JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.本文仅采撷其中的一例:JavaScri ...

  9. 浅谈JavaScript中继承的实现

    谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我 ...

随机推荐

  1. Redis for Windows(C#缓存)安装和使用

    Redis for Windows(C#缓存)安装和使用 前言 前段时间写过两篇简单的有关Memcached缓存的相关文章,当然了只是入门的如何使用而已.最近这两天又发现了Redis这个神奇的东西,之 ...

  2. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

  3. Fedora 23如何安装LAMP服务器

    LAMP 是开源系统上 Web 服务器的梦幻组合.LAMP 是 Linux. Apache HTTP 服务. MySQL/MariaDB 数据库和 PHP. Perl 或 Python 的简称. 下面 ...

  4. sublime自己常用到的设置

    一.快捷“在浏览器打开” 在首选项->按键绑定-用户中添加代码: { "keys": ["f12"], "command": &quo ...

  5. JAVA基础之String基本操作

    String str  = "str"; str.length(); //3       返回字符串长度 str.indexOf("s"); //0 返回s所在 ...

  6. 【Android 界面效果43】Android LayoutInflater的inflate方法中attachToRoot的作用

    我们在ListView的Adapter的getView方法里面经常会调用两个参数的inflate方法, mInflater.inflate(R.layout.adv_viewpager, null); ...

  7. android refbase类

    在Android的源代码中,经常会看到形如:sp<xxx>.wp<xxx>这样的类型定义,这其实是Android中的智能 指针.智能指针是C++中的一个概念,通过基于引用计数的 ...

  8. Android之EditText文本变化的监听

    监听EditText的文本变化需要给EditText控件加一个addTextChangeListener监听器 editText.addTextChangeListener(textWatcher); ...

  9. Java Script基础(八) Array数组对象

    一.Array数组 JavaScript中的数组也是具有相同数据类型的一个或者多个值得集合.用法和Java中的数组类似. Array对象的常用属性和方法: 属性: length:获取数组的长度: 方法 ...

  10. Hadoop2.0重启脚本

    Hadoop2.0重启脚本 方便重启带ha的集群,写了这个脚本 #/bin/bash sh /opt/zookeeper-3.4.5-cdh4.4.0/bin/zkServer.sh restart ...