- 三种方法都可改变函数
this
关键字的指向。apply()
接受一参数数组,返回函数执行的结果。call()
接受一组参数,返回函数执行的结果。bind()
接受一组参数,返回函数体。需在bind()
后加小括号才能执行函数。- 箭头函数的
this
绑定后不管使用apply()
、call()
仍是bind()
都不可修改。
this
关键字
- JavaScript中的函数存在
定义上下文
和运行上下文
,经过call()
、apply()
和bind()
能够改变this
的指向。this
总指向运行上下文。
定义上下文更准确的名称应该叫词法做用域,它指函数的定义部分所造成的做用域。javascript
function fun1 () {
// 函数fun1的词法做用域
// 函数定义
// ....
}
复制代码
函数在调用时会产生一个调用记录,其中包含函数在哪里被调用、传入函数的参数等信息。该记录也被称为运行上下文。一个函数的this
总指向函数的运行上下文。当fun1
在fun2
中调用时,fun1
的this
指向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()
都不可修改。对象