在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这三个方法,来改变函数体内部 this 的指向,因为函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念

apply、call

apply:应用某一对象的一个方法,用另一个对象替换当前对象

call:调用一个对象的一个方法,以另一个对象替换当前对象

function person() {}

person.prototype = {
attr: {age:18,sex:'girl'},
say: function() {
console.log("My age is " + this.attr.age);
console.log("I am a " + this.attr.sex);
}
} var Marry = new person();
Marry.say(); // My age is 18
// I am a girl

改变指向

function person() {}

person.prototype = {
attr: {age:18,sex:'girl'},
say: function() {
console.log("My age is " + this.attr.age);
console.log("I am a " + this.attr.sex);
}
} xiaoming ={ attr : {age:20,sex:'boy'} }; var Marry = new person();
Marry.say(); Marry.say.call(xiaoming);
// My age is 18
// I am a girl
// My age is 20
// I am a boy

共同之处

都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

不同之处

1、apply:最多只能有两个参数——新this对象和一个数组 argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里面。如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj,并且无法被传递任何参数。

fun.call(thisArg[, arg1[, arg2[, ...]]])

function f(x,y){
console.log(x+y);
}
f.call(null, 1, 1)
//return 2

2、call:则是直接的参数列表,主要用在js对象各方法互相调用的时候,使当前this实例指针保持一致,或在特殊情况下需要改变this指针。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

fun.apply(thisArg, [argsArray])

function f(x,y){
console.log(x+y);
}
f.call(null, [1,1])
//return 2

apply和call功能一样,只是传入的参数列表形式不同,其中 thisArg 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。  

如果某个函数的参数数量是不固定的,当你的参数是明确知道数量时用 call ,而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数,我们看一下一些用法

代码一

var array1 = [12 , "foo" , {name:"Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
console.log(array1);
//[12, "foo", Object, -2458, "Doe", 555, 100]

代码二

var numbers = [5, 458 , 120 , -215 ];
Math.max.apply(null,numbers);
//458

代码三

log(12 , "foo" , {name:"Joe"} , -2458);
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift('(app)');
console.log.apply(console, args);
};
// (app) 12 foo Object {name: "Joe"} -2458

bind

fun.bind(thisArg[, arg1[, arg2[, ...]]])

与上面不同的是,bind会返回一个改变this指向的新函数 ,注意这里强调的是新函数,其与之前的使用的不是同一块内存地址,所以当你需要重复使用这个函数的时候,你就不得不把其保存到一个变量,方便下次调用。上面的两个函数都是返回的执行结果,即调用即执

行,此外,另外需要注意的地方是,bind函数中的首个参数,会自动成为返回新函数中参数的默认值,那么正式调用的时候,只需要给出除首个参数外,剩余参数即可。

function f(x,y){
console.log(x+y);
}
f.call(null, [1,1])
var new_f = f.bind(null,1,1)
//return new function
new_f(1)
//return 2

需要说明的是,上面所有示例代码中的thisArg参数均用null来代替了,在未给出指定thisArg对象的情况下,null与undefined下this指向是全局对象,即js代码执行环境

具体可以参考  Javascript中bind()方法的使用与实现

apply、call、bind比较

var obj = {bar: 'Oops , this is a bad idea' };

var foo = {
get: function() {
return this.bar;
}
} var bind = foo.get.bind(obj) ,call = foo.get.call(obj) ,apply = foo.get.apply(obj); console.log(bind(),call,apply);
console.log(bind,call,apply); console.log(typeof bind,typeof call,typeof apply);
console.log(typeof bind(),typeof call,typeof apply);

看到区别没有,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;
bind是返回对应函数,便于稍后调用;apply、call则是立即调用

JavaScript中的call、apply、bind方法的区别的更多相关文章

  1. javascript中的call(),apply(),bind()方法的区别

    之前一直迷惑,记不住call(),apply(),bind()的区别.不知道如何使用,一直处于懵懂的状态.直到有一天面试被问到了这三个方法的区别,所以觉得很有必要总结一下. 如果有不全面的地方,后续再 ...

  2. JavaScript中call,apply,bind方法的区别

    call,apply,bind方法一般用来指定this的环境. var a = { user:"hahaha", fn:function(){ console.log(this.u ...

  3. 深入浅出:了解JavaScript中的call,apply,bind的差别

     在 javascript之 this 关键字详解文章中,谈及了如下内容,做一个简单的回顾:         1.this对象的涵义就是指向当前对象中的属性和方法.       2.this指向的可变 ...

  4. 浅析 JavaScript 中的 Function.prototype.bind() 方法

    Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个对象,bind() 方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数 ...

  5. 别真以为JavaScript中func.call/apply/bind是万能的!

    自从学会call/apply/bind这三个方法后我就各种场合各种使用各种得心应手至今还没踩过什么坑,怎么用?说直白点就是我自己的对象没有某个方法但别人有,我就可以通过call/apply/bind去 ...

  6. JavaScript 中的 Function.prototype.bind() 方法

    转载自:https://www.cnblogs.com/zztt/p/4122352.html Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个 ...

  7. Javascript中this作用域以及bind方法的重写

    这是一个最近遇到的笔试题,出于尊重,不会说出该公司的名字,源于自身比较少,笔试题是将bind方法用ES3重写,使用bind这个方法,导致一时半会懵了,只记得bind可以改变this的作用域. 作为查漏 ...

  8. Javascript中call,apply,bind方法的详解与总结

    在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...

  9. Javascript中call,apply,bind的区别

    一.探索call方法原理 Function.prototype.call = function(obj) { // 1.让fn中的this指向obj // eval(this.toString().r ...

  10. JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--前戏

    new关键字,call/apply/bind方法都和this的绑定有关,在学习之前,首先要理解this. 一起来学习一下this吧 首先.this是一个对象. 对象很好理解,引用类型值,可以实现如th ...

随机推荐

  1. JAVA nio 2 和 Path 类简介

    想要初步了解 NIO.2 API,也就是通常所说的“JSR203: More New I/O APIs for the Java Platform”,最好的切入点就是新的抽象类 java.nio.fi ...

  2. 解决hue报错:timed out (code THRIFTSOCKET): None

    报错栈: [/Jun/ :: +] decorators ERROR error running <function execute at 0x7fba2804ecf8> Tracebac ...

  3. MiniGUI ial 移植指南

    MiniGUI ial 移植指南 2.1 ial的定义 ial是一个通用的抽象输入接口,可以输入统一的数据的结构,也就是说在MiniGUI的核心代码里输入的数据的格式是固定的,不管输入设备是鼠标 还是 ...

  4. iOS:删除、插入、移动单元格

    删除.插入.移动单元格的具体实例如下:   代码如下: #import "ViewController.h" #define NUM 20 typedef enum { delet ...

  5. 全局安装 Vue cli3 和 继续使用 Vue-cli2.x

    官方链接:https://cli.vuejs.org/zh/guide/installation.html 1.安装Vue cli3 关于旧版本 Vue CLI 的包名称由 vue-cli 改成了 @ ...

  6. Javascript模块化工具require.js教程

    转自:http://www.w3cschool.cc/w3cnote/requirejs-tutorial-1.html, http://www.w3cschool.cc/w3cnote/requir ...

  7. Git 忽略规则 .gitignore文件 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  8. MediaPlayer 状态机 API 详解 示例

    简介 public class android.media.MediaPlayer extends Object implements VolumeAutomation 可能需要的权限: One ma ...

  9. jquery获得select option的值和对select option的操作

    <body> <select name="month" id="selMonth" onchange="set()"> ...

  10. Android GUI之View布局

    在清楚了View绘制机制中的第一步测量之后,我们继续来了解分析View绘制的第二个过程,那就是布局定位.继续跟踪分析源码,根据之前的流程分析我们知道View的绘制是从RootViewImpl的perf ...