JavaScript中的this一直是个大坑,现在,总结的this的一些规律(革命尚未成功,同志仍需努力):
直接调用的都是window
除非是bind绑定过的,其他情况下,直接调用的方法的this都是window。所谓的直接调用,就是直接以method()的形式调用,没有call, apply, new
看几种情况:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
function
foo(){
return
this
;
}
foo();
// window
var
obj = {
foo:
function
(){
return
this
; }
}
var
foo = obj.foo;
foo();
// window
function
Foo(){
this
.foo =
function
(){
console.log(
this
);
}
var
foo =
this
.foo;
foo();
// window
}
new
Foo();
谁调用,谁是
this
除非是bind绑定过的,一般情况下,谁调用这个方法,那么内部的
this
就指向这个对象。也就是说obj.method(),那么就指向obj。obj.foo.method(),那么就指向obj.foo
看几个例子:
var
obj = {
foo:
function
(){
return
this
; }
}
obj.foo();
// obj调用,所以结果是obj
function
foo(){
return
this
};
var
obj = {};
obj.foo = foo;
obj.foo();
// obj调用,所以结果是obj
var
obj = {
bar:
function
(){
return
this
; },
foo:
function
(){
return
this
.bar();
}
}
obj.foo();
// 在foo中, this是obj, 而this调用的bar, 所以返回的是obj
var
obj = {
bar: {
foo:
function
(){
return
this
}
}
}
obj.bar.foo();
// obj.bar调用的foo,所以返回的结果是bar
function
foo(){
this
.bar =
function
(){
return
this
}
return
this
.bar();
}
foo();
// 由于foo中的this是window, 所以this.bar()返回的是window
function
Foo(){
this
.foo =
function
(){ console.log(
this
); }
this
.foo();
}
var
object =
new
Foo();
// 由于this.foo中的this是object,所以this是object
|
new会生成一个新的this
所有情况下,(箭头函数不能使用new关键字),使用了new以后,会把内部的this指向新生成的对象。
除去bind的情况下,prototype中的this也指向新生成的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function
Foo(){
console.log(
this
);
// this指向新生成的对象,object
}
var
object =
new
Foo();
function
Foo(){
this
.foo =
function
(){
return
this
=== object; }
}
var
object =
new
Foo();
object.foo();
// 输出true
function
Foo(){}
Foo.prototype.foo =
function
(){
return
this
=== object; }
var
object =
new
Foo();
object.foo();
// 输出true
|
call, apply是谁,this就是谁
除非是bind的情况,call, apply是谁,那么内部的this就是谁。
注意:如果是基本类型,那么javascript会把基本类型转换成Object的形式
也是看例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function
foo(){
return
this
; }
foo.call(
"a"
);
// String
typeof
foo.call(
"a"
);
// object
var
obj = {
foo :
function
(){
return
this
; }
}
obj.foo.call(1);
// Number
typeof
obj.foo.call(1);
// object
function
Foo(){
this
.foo =
function
(){
return
this
; }
}
var
object =
new
Foo();
object.foo.call(1);
// Number
|
bind是谁,this就是谁
除了new这一种特殊情况,bind的对象是谁,那么this也就是谁。即使call, apply也没有权利改变。
注意:如果是基本类型,那么javascript会把基本类型转换成Object的形式
1
2
3
4
5
6
7
8
9
10
11
|
function
foo() {
return
this
; }
foo = foo.bind(1);
foo();
// Number
typeof
foo();
// object
function
foo() {
return
this
; }
foo = foo.bind(1);
foo.call(
"a"
);
// Number 1
function
Foo() {
return
this
; }
Foo.prototype.foo = (
function
(){
return
this
; }).bind(1);
var
object =
new
Foo();
object.foo();
// Number
|
特殊情况
new这个关键词可以改变方法内部的this,使他指向新生成的对象
1
2
3
4
|
function
Foo(){
this
.foo =
function
(){ console.log(
this
=== obj) } }
Foo = Foo.bind(1);
var
obj =
new
Foo();
obj.foo();
// 输入true
|
箭头函数
箭头函数的this是根据定义环境的this来定的,也就是说定义的函数周围的this是什么,它的this就是什么。
而且不会被bind, call, apply所改变
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
28
29
30
31
32
33
34
35
36
37
38
39
|
var
foo = ()=>{
return
this
};
foo()
// window
var
obj = { foo: ()=>
this
}
obj.foo();
// 由于定义的时候,周围的环境是window,所以返回window
var
obj = {
foo(){
var
bar= ()=>{
return
this
};
return
bar();
}
}
obj.foo();
// 由于定义bar的时候,周围环境是obj,所以返回obj
var
foo = obj.foo;
foo();
// 同理,这里是window
var
foo = ()=>{
return
this
};
foo = foo.bind(1);
foo();
// window
foo.call(1);
// window
foo.apply(1);
// window
function
Foo(){
// 箭头函数
var
a = ()=>{
console.log(
this
=== object);
// true
}
// 对比普通函数
var
b =
function
(){
console.log(
this
=== window);
// true
}
this
.foo =
function
(){
a(); b();
}
}
var
object =
new
Foo();
object.foo();
function
Foo(){}
// window
Foo.prototype.foo = ()=>{
return
this
}
// window
var
object =
new
Foo();
|
object.foo(); // 由于定义foo的时候,周围环境是window,所以这里是window