什么是this
this 是执行上下文中的一个属性(上下文就是指的是一种环境),是指包含它的函数作为方法被调用时所属的对象。听不懂,换种方式解读.
一个函数包含了this,这个函数在哪一个对象里面被调用了,this就是指向这个对象.
- 一个函数包含了
this. - 对象里面被调用了这个函数.
this指向这个对象
this的规则
-
默认绑定
-
this所处的词法作用域在哪里生效了,this就绑定在哪里-在严格模式下,全局对象无法进行默认绑定,所以导致
this只能绑定在undefined上
var a = 5
function fun(){
var a = 3;
console.log(this.a)
}
fun() // 5
因为fun函数在全局window上被调用,this指向window.所以此时this.a打印5
-
隐式绑定
-当函数引用有上下文对象时,隐式绑定的规则就会把函数调用中的
this绑定到这个上下文对象var a = 3 function fun1(){ var a = 1; console.log(this.a) } var obj = { a:2, fun1:fun1, //将函数fun1的引用赋值给obj.fun1属性. } obj.fun1() // 打印 2 fun1() // 打印 3此时在obj里调用函数的引用,
this指向这个对象. -
隐式丢失
-当隐式绑定的函数丢失了绑定对象,就会应用默认绑定
var a = 3 function fun2(){ var a = 1; console.log(this.a) } var obj = { a:2, fun2:fun2 } var change = obj.fun2; change() // 3这种情况被称为隐式丢失,其实很好理解.将
fun2的引用作为值传给obj.fun2,此时在把obj.fun2传给变量change,就相当于直接把fun2的引用赋值给变量change.也就相当于fun2直接在全局下被调用.此时又变回了第一种规则,默认绑定.所以this.a为 3 -
显示绑定 用call(),apply(),bind()方法更改
this的绑定
a.call(obj)b.apply(obj)var bar = foo.bind(obj);bar()-call,apply,bind可以强行指定一个函数的this的指向
var a = 3
function fun3(){
var a = 1;
console.log(this.a)
}
var obj = {
a:2,
}
fun3.call(obj); // 2
fun3.apply(obj); // 2
fun3.bind(obj)(); // 2 bind()会有个返回值,而返回值是一个函数 所以还要在后面加一个括号
fun3() // 3
这三个方法都可以改变this的指向,既然都是可以改变this的指向,那么为什么要三个呢.当然是有一点小小的去别的.
call传入的参数数量不固定,跟apply相同的是,第一个参数也是代表函数体内的this指向,从第二个参数开始往后,每个参数被依次传入函数。apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply方法把这个集合中的元素作为参数传递给被调用的函数。bind与call不同的是bind会有个返回值,这个返回值是一个函数,作用和bind作用的函数功能一样.
显示绑定原理
其实这些方法是巧妙的运用了隐式绑定的规则,通过往对象中添加属性值为改函数的引用来改变this的指向.
这里我们用call举例,怎么手动实现call方法.
function myCall(obj,...arg){
if(typeof this !== 'function'){
console.log('type error')
}
obj.fn = this; //向obj对象中添加 添加属性,将调用函数设为对象的方法
const res = obj.fn(...arg); //将结果保存到一个变量中
delete obj.fn;//删除对象中的属性
return res;
}
这样一个改变this指向的方法就被创建出来了.
this的调用模式
既然了解了this的规则,那么this的调用模式也就能很好理解了.
-
第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,
this指向全局对象。 -
第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,
this指向这个对象。 -
第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。
-
第四种是
apply、call和bind调用模式,这三个方法都可以显示的指定调用函数的this指向。其中apply方法接收两个参数:一个是this绑定的对象,一个是参数数组。call方法接收的参数,第一个是this绑定的对象,后面的其余参数是传入函数执行的参数。也就是说,在使用call()方法时,传递给函数的参数必须逐个列举出来。bind方法通过传入一个对象,返回一个this绑定了传入对象的新函数。这个函数的this指向除了使用new时会被改变,其他情况下都不会改变。
总结
希望通过本片文章能够更加清楚的了解this的相关知识,欢迎各位给予建议.