浅谈JavaScript中的apply、call和bind

摘要

  • 三种方法都可改变函数this关键字的指向。
  • apply()接受一参数数组,返回函数执行的结果。
  • call()接受一组参数,返回函数执行的结果。
  • bind()接受一组参数,返回函数体。需在bind()后加小括号才能执行函数。
  • 箭头函数的this绑定后不管使用apply()call()仍是bind()都不可修改。

浅析this关键字

  • JavaScript中的函数存在定义上下文运行上下文,经过call()apply()bind()能够改变this的指向。
  • this总指向运行上下文

定义上下文

定义上下文更准确的名称应该叫词法做用域,它指函数的定义部分所造成的做用域。javascript

function fun1 () {
	// 函数fun1的词法做用域
	// 函数定义
	// ....
}
复制代码

运行上下文

函数在调用时会产生一个调用记录,其中包含函数在哪里被调用、传入函数的参数等信息。该记录也被称为运行上下文。一个函数的this总指向函数的运行上下文。当fun1fun2中调用时,fun1this指向fun2的定义上下文(词法做用域)。java

function fun2 () {
    // fun1的this指向该做用域
    fun1();
    // 函数定义
    // ...
}
复制代码

this的指向

this是运行上下文的一个属性,所以常说this指向函数的运行上下文
this是在函数调用时被绑定的,与函数的声明位置(即词法做用域)没有任何关系。数组


call()apply()

call()

call()方法的第一个参数为要指定的this对象,第二个参数及之后为函数运行所需的参数列表。app

let obj = {
    a: 1
}

function fun1 (num1, num2) {
    console.log(this); // obj {a: 1}
    console.log(num1 + num2); // 3
    console.log(this.a); // 1
}

fun1.call(obj, 1, 2);
复制代码

上述代码展现了call()的两种能力。一方面它改变了fun1调用时的this关键字,让其指向obj,并经过this关键字来访问obj中的属性。另外一方面它将本身接受到的参数传入fun1函数

apply()

call()apply()本质上并没有太大差异,惟一的区别在于call()接受的是参数列表,而apply()接受的是一个参数数组。ui

// ··· 同上
    fun1.apply(obk, [1, 2]); // 效果和fun1.call(obj, 1, 2)相同
复制代码

bind()

bind()建立一个新的函数, 当这个新函数被调用时this键值为其提供的值,其参数列表前几项值为建立时指定的参数序列。          ----- MDNthis

bind()的使用方法和call()十分相似,它的第一个参数是须要绑定的this对象,以后的参数为函数运行所需的参数列表。下面让咱们来试验一下。spa

let obj = {
    a: 1
}

function fun1 (num1, num2) {
    console.log(this);
    console.log(num1 + num2);
    console.log(this.a);
}

fun1.bind(obj, 1, 2); // fun1 { ··· }
复制代码

不一样于apply()call()bind()返回的并非fun1执行完毕的返回值,而是更改了this并初始化参数以后的fun1的函数定义。所以,要执行fun1,需在bind()后面再加一对括号:code

fun1.bind(obj, 1, 2)(); // 改变this并传入参数后执行fun1
复制代码

apply()call()bind()的比较

相同点

  • 都可改变函数this关键字的指向。

不一样点

  • apply()接受一参数数组,返回函数执行的结果。
  • call()接受一组参数,返回函数执行的结果。
  • bind()接受一组参数,返回函数体。需在bind()后加小括号才能执行函数。

箭头函数的this绑定

ES6中新加入了箭头函数,它的绑定彻底继承自调用它的做用域。绑定后不管使用apply()call()仍是bind()都不可修改对象

相关文章
相关标签/搜索