this指向
说明
this指向笔记总结
# this指向
this在运行时被绑定
# 默认绑定
独立函数调用 函数没有被绑定到对象上进行调用
函数调用时无任何调用前缀的情景,this指向全局对象。在严格模式环境中,默认绑定的this指向undefined
function f1() {
console.log(this);
f2()
}
function f2() {
console.log(this);
}
f1() // window window
----------------------------------
function foo(fun) {
fun()
}
let obj = {
name: "rio",
bar:function(){
console.log(this);
}
}
foo(obj.bar) // window
--------------------------------------
let obj = {
name: "rio",
bar:function(){
console.log(this);
}
}
let f = obj.bar
f() // window
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
# 隐式绑定
函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上
如果函数调用前存在多个对象,this指向距离调用自己最近的对象
let obj = {
name: "rio",
bar:function(){
console.log(this);
}
}
obj.bar(); // {name: 'rio', bar: ƒ}
------------------------
function fn() {
console.log(this.name);
};
let obj = {
name: 'o1',
func: fn,
};
let obj1 = {
name: 'o2',
o: obj
};
obj1.o.func() // o1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# new绑定
- 创建新的空对象
- 将this指向这个空对象
- 执行函数体中的代码
function f1() {
console.log(this);
this.name = "rio"
}
new f1()
2
3
4
5
# 显式绑定
apply 、call 和 bind 这三个方法都可以显示的指定调用函数的 this 指向。apply接收参数的是数组,call接受参数列表; bind方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this指向除了使用new 时会被改变,其他情况下都不会改变。
三者第一个参数都是this
要指向的对象,如果如果没有这个参数或参数为undefined
或null
,则默认指向全局window
# call
call 第一个参数是绑定的this 后面传入的是一个参数列表即 后续参数会作为实参传入
let obj = {
name: 'rio',
age: 20
}
function foo() {
console.log(this);
}
foo.call(obj) // {name: 'rio', age: 20} 强制函数中的this指向obj
foo.call(123); // Number {123}
foo.call('123'); // String {'123'}
----------------------------------------------
function foo(name,age,height) {
console.log(this);
console.log(name,age,height);
}
foo.call("call",'rio',20,175) // String {'call'} rio 20 175
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# apply
apply 第一个参数是绑定的this 第二个参数是传入的实参以数组形式
function foo(name,age,height) {
console.log(this);
console.log(name,age,height);
}
foo.apply("apply",['rio',20,175]) // String {'apply'} rio 20 175
2
3
4
5
# bind
bind 第一个参数是this
的指向, 后面传入的是一个参数列表即 后续参数会作为实参传入
不会像call和apply那样立即执行,而是返回一个永久改变this
指向的函数
function foo(name,age,height) {
console.log(this);
console.log(name,age,height);
}
let obj = {
name: 'rio'
}
let bar = foo.bind(obj,'ami',20,175);
bar(); // {name: 'rio'} ami 20 175
2
3
4
5
6
7
8
9
# 绑定的优先级
- new
- bind
- apply/call
- 隐式绑定
- 默认绑定
new不能和apply/call一起使用
# 忽略显示绑定
如果在显示绑定中,我们传入一个null或者undefined,那么这个显示绑定会被忽略,使用默认规则:
function foo() {
console.log(this);
}
foo.apply("abc") // String {'abc'}
foo.apply(null) // window
foo.apply(undefined) // window
2
3
4
5
6
7
# 间接函数调用
创建一个函数的间接引用,这种情况使用默认绑定规则。
var name = "windowName"
var person = {
name: "person",
say(){
console.log(this.name);
}
}
function say() {
var s = person.say
s(); // windowName
person.say(); // person
(f = person.say)() // windowName
}
say()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 箭头函数
箭头函数不会绑定this没有this、arguments属性;
function foo() {
console.log(this);
}
bar = ()=>{
console.log(this);
}
foo.apply('bbbb'); // String {'bbbb'}
bar.apply('aaaa'); // Window
------------------------------------
let mes = 'global'
let obj = {
mes: "obj",
foo: function () {
let bar = () => {
console.log(this);
console.log(mes);
}
return bar;
}
}
let fn = obj.foo()
// bar 是箭头函数
fn.apply("bbb") // {mes: 'obj', foo: ƒ} global
---------------------------------------------------
function foo() {
var bar = () => {
console.log(arguments)
}
bar()
}
foo(111, 222) //Arguments(2) [111, 222, callee: ƒ, Symbol(Symbol.iterator): ƒ]
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
箭头函数不能作为构造函数来使用,不能和new一起来使用(箭头函数没有原型);
# 箭头函数应用
function request(url,callback) {
var res = ["a","b","c"]
// 默认绑定
callback(res)
}
let obj = {
name: [],
network:function(){
var _this = this
request("/xxx",function(res) {
console.log(res); // ['a', 'b', 'c']
console.log(this); // window
console.log(_this); // {name: Array(0), network: ƒ}
_this.name = _this.name.concat(res)
})
}
}
obj.network()
console.log(obj.name); // ['a', 'b', 'c']
-----------------------------------------------------
// 箭头函数没有this 会直接找上层this
function request(url,callback) {
var res = ["a","b","c"]
callback(res)
}
let obj = {
name: [],
network:function(){
request("/xxx",(res)=> {
console.log(this); // {name: Array(0), network: ƒ}
this.name = this.name.concat(res)
})
}
}
obj.network()
console.log(obj.name); // ['a', 'b', 'c']
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
# 练习
var name = "name";
var person1 = {
name: 'person1',
f1:function () {
console.log(this.name);
},
f2: ()=>{
console.log(this.name);
},
f3:function(){
return function () {
console.log(this.name);
}
},
f4:function () {
return ()=>{
console.log(this.name);
}
}
}
let person2 = {
name: 'person2'
}
person1.f1(); // person1
person1.f1.call(person2); // person2
person1.f2(); // name
person1.f2.call(person2); // name
person1.f3()(); // name
person1.f3.call(person2)(); // name
person1.f3().call(person2); // person2
person1.f4()(); // person1
person1.f4.call(person2)(); // person2
person1.f4().call(person2); // person1
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
# 参考
js 五种绑定彻底弄懂this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解 - 听风是风 - 博客园 (cnblogs.com) (opens new window)
MDN Web Docs (mozilla.org) (opens new window)
JavaScript高级程序设计(第4版)