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. Javascript模块化编程系列三: CommonJS & AMD 模块化规范描述

    CommonJS Module 规范 CommonJS 的模块化规范描述在Modules/1.1.1 中 目前实现此规格的包有: Yabble,CouchDB,Narwhal (0.2), Wakan ...

  2. dsPIC33EP timer1 初始化设置及应用

    //文件 p33timer1.h #ifndef _P33TIMER1_H_ #define _P33TIMER1_H_ //#include "p33timer1.h" #def ...

  3. iOS开发——多线程OC篇&多线程总结

    多线程总结 //1.NSThread /** 优点:NSThread 比其他两个轻量级. 缺点:需要自己管理线程的生命周期,线程同步,线程同步时对数据的加锁会有一定的系统开销. cocoa给我提供了两 ...

  4. 你应该知道的基础 Git 命令

    我们在早先一篇文章中已经快速介绍过 Vi 速查表了.在这篇文章里,我们将会介绍开始使用 Git 时所需要的基础命令. Git Git 是一个分布式版本控制系统,它被用在大量开源项目中.它是在 2005 ...

  5. 基础知识 - Golang 中的正则表达式

    ------------------------------------------------------------ Golang中的正则表达式 ------------------------- ...

  6. Golang学习 - strconv 包

    ------------------------------------------------------------ // 将布尔值转换为字符串 true 或 false func FormatB ...

  7. spring security源码分析之web包分析

    Spring 是一个非常流行和成功的 Java 应用开发框架.Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案.一般来说,Web 应用的安全性包括 ...

  8. 使用jmeter对ActiveMQ集群性能方案进行评估--转载

    原文地址:http://www.51testing.com/html/78/23978-143163.html 1.测试概要1.1 关于这篇文档中涉及的基于JMS的消息系统能为应用程序提供可靠的,高性 ...

  9. c++ 设计模式3 (重构技法 Template Method)

    1. 重构 面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指的是那些可以满足 “应对变化,提高复用”的设计. 设计模式的要点是“寻找变化点,然后在变化点处应用设计模式,从而更好地理解 ...

  10. ios-UIPickerView基本使用

    #import "ViewController.h" @interface ViewController ()<UIPickerViewDataSource,UIPicker ...