一:关于普通函数调用的this问题
函数执行上下文中的this
1 | function foo(){ |
这段代码中this是指向全局的,那么有什么方法来改变函数执行上下文中的this呢?
1)通过函数的call方法设置。1
2
3
4
5
6
7
8
9let bar = {
myName : " 极客邦 ",
test1 : 1
}
function foo(){
this.myName = " 极客时间 "
}
foo.call(bar)//foo.call方法为了改变this的指向,让其指向bar。bar中myName的值更换为极客时间。
console.log(bar)
2)通过对象调用方法设置1
2
3
4
5
6
7
8
9
10var myObj = {
name : " 极客时间 ",
showThis: function(){
console.log(this)
}
}
myObj.showThis()//相当与myObj.showThis.call(myObj)方法调用,这里的this指向myObj这个对象。
var obj = myObj.showThis
obj()//这样调用的话myObj里的showThis中的this为window这个对象
下面介绍几种特殊的情况。
1 解析:fn函数里的this还是obj对象,但调用f()函数时,里面的this变成全局的window了。1
2
3
4
5
6
7
8
9
10
11var obj = {
x: 10,
fn: function() {
function f() {
console.log(this);
console.log(this.x);
}
f();
}
};
obj.fn();
2 解析:会先打印Aurelio De Rosa,之后打印John Doe。因为前一个相当于obj.prop来调用,后一个相当于全局window来调用。1
2
3
4
5
6
7
8
9
10
11
12
13var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname())
var test = obj.prop.getFullname;
console.log(test());
3)通过构造函数中设置1
2
3
4function CreateObj(){
this.name = " 极客时间 "
}
var myObj = new CreateObj()
这里的this相当于CreateObj这个函数
二:关于立即执行函数和箭头函数以及setTimeout的this问题
1 解析:会先打印bar,bar 之后undefined和bar。立即执行函数里的this为window,所以为undefined。但是self还是为myObject这个对象。1
2
3
4
5
6
7
8
9
10
11
12
13var myObject = {
foo: "bar",
func:function(){
var self = this;
console.log(this.foo);
console.log(self.foo);
(function(){
console.log(this.foo);
console.log(self.foo);
}())
}
}
myObject.func();
2 这里我们看一下另一种情况:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const person = {
name: 'menglinghua',
say: function (){
return function (){
console.log(this)//这里的this指向window
console.log(this.name);
};
}
};
person.say()(); // undefined
const person = {
name: 'menglinghua',
say: function (){
return () => {
console.log(this.name);
};
}
};
person.say()(); // menglinghua
3 解析:分别打印(1){x: 10, test: ƒ, test1: ƒ, test2: ƒ, test3: ƒ} 10
(2)Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} 1
(3){x: 10, test: ƒ, test1: ƒ, test2: ƒ, test3: ƒ} 10
(4)Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} 1
总结:箭头函数找父级作用域即可,es6的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的this取决于它的外部函数。setTimeout普通写法可以认为window调用的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28var x = 1
var o = {
x:10,
test:function(){
console.log(this)
console.log(this.x)
},
test1:()=>{
console.log(this)
console.log(this.x)
},
test2:function(){
setTimeout(()=>{
console.log(this)
console.log(this.x)
},100)
},
test3:function(){
setTimeout(function(){
console.log(this)
console.log(this.x)
},100)
},
}
o.test()
o.test1()
o.test2()
o.test3()
那么如何解决setTimeout的这种this指向的这种问题呢?看如下这一段代码:1
2
3
4
5
6
7
8var name= 1;
var MyObj = {
name: 2,
showName: function(){
console.log(this.name);//这里的this指向window的,会打印1
}
}
setTimeout(MyObj.showName,1000)
两种街解决方案:如下
1)箭头函数和function函数的写法1
2
3
4
5
6
7
8// 箭头函数
setTimeout(() => {
MyObj.showName()
}, 1000);
// 或者 function 函数
setTimeout(function() {
MyObj.showName();
}, 1000)
2)绑定bind函数,改变内部的this指向,返回一个函数。1
setTimeout(MyObj.showName.bind(MyObj), 1000)
三:关于构造函数new的this问题1
2
3
4
5
6
7
8
9
10var num1=10,num2=20;
function add(){
var num1 = 1,num2 = 2
console.log(this.num1 + this.num2)
}
add()//30,this为window
new add()//add()里this为add{},只有this.num3=30,才会向里赋值。对于var num1 = 1,num2 = 2,不会对其造成影响,所以打印出来还是NaN
var mm = add.bind({num1:200,num2:300})
mm()//500,bind改变this的指向
new mm()//还是add{}空对象,为NaN