this指向问题
在我们研究this指向问题的时候,我们只需要知道判断this时,那个对象调用它,它就指向谁;否则就指向全局对象window,牢记这一点,我们就能很好的解决this指向问题。
1.普通函数调用
当普通函数调用时,this没啥特殊意外,就是指向全局对象window。
let name = "Mick";
function f(){
console.log(this); //window
console.log(this.name); // 'undefine' 相当于window.name
}
f();
上面代码中,因为函数f,没有人调用它所以f就会指向全局对象window,可能你会疑惑为什么this.name不会输出Mick,但是你仔细看一下,name定义的方式时let,不属于window对象,所以。(在这里我们需要注意一下,在es6中,新规定var,function声明的全局变量,仍然属于顶级对象的属性;使用let,const,class声明的全局变量不再属于顶层对象的属性)
2.对象函数调用
这个我们只需记住一点,谁调用它,this就指向谁
var name = 'window'
let obj1 = {
name: 'obj',
sayHi: function() {
console.log(this.name)
},
sayFoo: function () {
return function(){
console.log(this.name)
}
}
}
obj1.sayHi(); //"obj"
obj1.sayFoo()(); //"window"
let f = obj1.sayHi;
f(); //"window"
上面代码中,obj1.sayHi()的输出结果,想必我们都能理解,但是f()和obj1.sayFoo()()的输出结果,可能大家就会感到很疑惑了把,为什么都是window呢,而不是obj呢,这里我们就得想起那句很重要的话了,谁调用它,this就指向谁,否则就指向window。当我们把这句话理解了,那上面的输出结果我们就会很好理解了。
在obj1.sayFoo()()这个语句中,我们可以看到,obj1调用了sayFoo()这个函数,那么为什么不输出obj呢?这里我们就得知道,sayFoo()的确是指向obj1这个对象的,但是sayFoo()这个函数会返回一个匿名函数,所以obj1.sayFoo()()这个语句就等价于了一个匿名函数f(),但是这个函数没有人调用它,所以说这里的this.name才会是window。
那么f()就和上面是一样的道理,在上述语句中,我们是将obj1.sayHi这个函数的表达式,赋值给了f,此时的f就相当于是一个新的函数,其值为function() { console.log(this.name) },当我们执行函数f的时候,会发现没有人调用它,所以它的this指向就会指向全局window,看到这里我想对象调用这个就不会难到大家了把。
3.箭头函数调用
这个我们就得注意了,箭头函数比较特殊,它是没有this指向的。箭头函数的this指向是继承外面的环境的,我们在研究它的this指向的时候,需要取往他的父级找,箭头函数的this指向它的父级的指向。
var name = 'window'
let obj1 = {
Ithis:this,
name: 'obj',
sayHi: ()=> {
console.log(this.name)
},
sayFoo: ()=> {
return ()=>{
console.log(this.name)
}
},
sayHello: function(){
return ()=>{
console.log(this.name);
}
}
}
console.log(obj1.Ithis); //window对象
obj1.sayHi(); //"window"
obj1.sayFoo()();//"window"
obj1.sayHello()();//"obj"
上述代码中,obj1.sayHi()执行时,sayHi指向了obj1但是由于sayHI是一个箭头函数,所以它的this指向就是obj1的this指向,但是obj1的this是window对象,所以说会输出window。
对于obj1.sayFoo()()这个语句,首先sayFoo函数返回一个匿名的箭头函数,该匿名箭头函数this指向的就是sayFoo函数的this,而sayFoo也是一个箭头函数,所以它的this指向window,所以返回的匿名的箭头函数this指向window
obj1.sayHello()(),首先sayHello会返回一个匿名箭头函数,该函数指向的是sayHello的this,而sayHello函数是一个普通函数,并且obj1调用了它,所以会输出obj。
4. call、apply、bind
call、apply、bind可以改变函数内部的this指向,但由于箭头函数自身没有this,所以call、apply、bind对箭头函数是不起作用的
var name = 'window'
let obj3 = {
name: 'obj',
sayHi: () => {
console.log(this.name)
},
sayFoo: function () {
console.log(this.name)
}
}
let obj4 = {
name: 'other'
}
obj3.sayHi.call(obj4) // window,call对箭头函数不起作用
obj3.sayFoo.call(obj4) // other,call可以改变函数内部的this到指定变量
关于this指向的问题,我就谈就到这里,希望对大家有所帮助。