this指向
-
setTimeout/setInterval
setTimeout(function(){console.log(this)},1000); //window
-
监听点击
const boxDiv = document.querySelector('.box') boxDiv.onclick = function (){console.log(this)}; //this => boxDiv
-
Array.forEach/map/filter/find
const arr = [1,2,3] arr.forEach(function(item){console.log(item,this)}) //1,window 2,window 3,window
//Array.forEach(function(){},this) 当我们在函数后添加变量,则此时this指向该变量 const arr = [1,2,3] const obj = {age : 20} arr.forEach(function(item){console.log(item,this)},obj) //1,{age:20} 2,{age:20} 3,{age:20}
this绑定规则优先级
默认规则最低
显示绑定高于隐式绑定
//call、apply高于隐式绑定 const obj = { foo:function(){ cosnole.log(this) } } obj.foo(); //this => obj obj.foo.call('aaa'); //this => 'aaa' obj.foo.apply('bbb'); //this => 'bbb' //bind高于隐式绑定且高于call、apply function foo(){ console.log(this) } const obj = { foo : foo.bind('aaa') } obj.foo(); //this => 'aaa'
new绑定高于隐式绑定
var obj = { foo:function(){ console.log(this) } } var f = new obj.foo() //this => foo
new绑定高于显示绑定
//new关键字不能和apply、call一起使用 function foo(){ console.log(this) } var bar = foo.bind('aaa') var obj = new bar() //this => foo
this规则之外
apply、call、bind:当传入null、undefined时,自动将this绑定为全局对象
function foo(){
console.log(this)
}
foo.apply(null); // this => window
foo.call(undefined); // this => window
var bar = foo.bind(null)
bar(); //this => window
间接函数调用
var obj = {
foo:function(){
console.log(this)
}
}
var obj2 = {}
obj2.bar = obj.foo
obj2.bar(); //this => obj2
//当出现这种情况时指向window
var obj1 = {
foo:function(){
console.log(this)
}
}
var obj2 = {};
(obj2.bar = obj1.foo)(); //this => window
//此时相当于独立函数,即foo()
function foo(el){
console.log(el,this)
}
var obj = {}; // <== 此处必须要加分号,否则报错,以为下一行与此处为一个整体
[1,2,3].forEach(foo,obj);
//1,obj 2,obj 3,obj
箭头函数没有自己的this,依托上层作用域的this
var obj = {
data : [],
foo:function(){
setTimeout(function(){
var result = [1,2,3]
this.data = result //指向window
},1000)
}
}
var obj = {
data : [],
foo : function (){
var _this = this
setTImeout(function(){
var result = [1,2,3]
_this.data = result //指向obj中的this,闭包
},1000)
}
}
var obj = {
data : [],
foo : function(){
setTimeout(()=>{
var result = [1,2,3]
this.data = result //指向上层作用域中的this
})
}
}
经典面试题
var person = {
sayName : function (){
console.log(this)
}
}
function sayName(){
var sss = person.sayName; // sss = function(){coonsole.log(this)}
sss(); //window 独立函数 function(){console.log(this)}
person.sayName(); //person
(person.sayName)(); //与上一行相同 person
(b = person.sayName)(); //window 等同于function(){console.log(this)}
}
sayName();
对象不生成作用域,只有函数会有作用域
var person1 = {
foo1 : function (){
console.log(this)
},
foo2 : ()=> console.log(this),
foo3 : function(){
return function(){
console.log(this)
}
},
foo4 : function(){
return ()=>console.log(this)
}
}
var person2 = {}
person1.foo1(); //person1 隐式绑定
person1.foo.call(person2); //person2 显示绑定
person1.foo2(); //window 箭头函数依托上层作用域,此时为全局
person1.foo2.call(person2); //window
person1.foo3()(); //window 独立函数调用
person1.foo3.call(person2); //window
person1.foo3().call(person2); //person2
peson1.foo4()(); //person1 箭头函数不绑定this,上层作用域中的this指向parson1
person1.foo4.call(person2)(); //parson2 上层作用域被显示绑定person2
person1.foo4().call(person2); //parson1
function Person (){
this.foo1 : function (){
console.log(this)
},
this.foo2 : ()=>console.log(this),
this.foo3 : function (){
return function (){
console.log(this)
}
},
this.foo4 : function (){
return ()=>console.log(this)
}
}
var person1 = new Person();
var person2 = new Person();
person1.foo1(); //person1
person1.foo1.call(person2); //person2
person1.foo2(); //person1
person1.foo2.call(person2); //person1
person1.foo3()(); //window
person1.foo3.call(person2)(); //window
person1.foo3().call(person2); //person2
person1.foo4()(); //perosn1
person1.foo4.call(person2)(); //person2
peron1.foo4().call(person2); //person1
function Person (){
this.obj = {
foo1 : function (){
return function (){
console.log(this)
}
},
foo2 : function (){
retuen ()=>console.log(this)
}
}
}
var person1 = new Person();
var person2 = new Person();
person1.obj.foo1()(); //window
person1.obj.foo1.call(person2)(); //window
person1.obj.foo1().call(person2); //person2
person1.obj.foo2()(); //obj
person1.obj.foo2.call(person2)(); //person2
person1.obj.foo2().call(person2); //obj