js中的this

常识

this 的 scope 由函数/类分隔

普通函数

普通函数即用 函数声明 或 函数表达式 定义的函数

把所有函数调用都转换成显式的 call() 调用

Function Invocation Pattern

1
foo(); // foo.call(undefined);

默认模式下当你传的 context 为 undefined 时,默认的 context为Global对象,在浏览器中就是window对象

strict模式下此时 this 即为 undefined

Method Invocation Pattern

1
2
3
4
var obj = {
foo: function () { }
}
obj.foo(); // obj.foo.call(obj)

Constructor Pattern

foo函数内部的this永远是new foo()返回的对象

1
2
3
4
let c = new class {
foo () { }
}
c.foo(); // c.foo5.call(c);

Apply Pattern

call() 方法的作用和 apply() 方法类似,只有一个区别,就是 call() 方法接受的是若干个参数的列表,而 apply() 方法接受的是一个包含多个参数的数组

箭头函数

在箭头函数出现之前,每个新定义的函数都有它自己的 this 值,this 被证明是令人厌烦的面向对象风格的编程

箭头函数 中,this 与封闭词法上下文的 this 保持一致。

箭头函数在设计中使用的是Lexical this,即这个函数被创建时的 this 就是函数内部的 this

需要注意的是,函数创建时并不是读代码的人第一次肉眼能看到这个函数的时候

例子

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
'use strict';

let a = function () {
let foo1 = () => console.log(this);
let foo2 = function () { console.log(this); };
foo1();
foo2();
}
a();
// undefined, undefined
a.call('nico');
// nico, undefined

let b = {
foo3: () => console.log(this),
foo4: function () { console.log(this); },
};
b.foo3();
// Window {...}
b.foo4();
// { foo3: f, foo4, f}

let c = new class {
foo5 () { console.log(this); }
}
c.foo5();
// { }

参考资料

this - JavaScript | MDN

箭头函数 - JavaScript | MDN

如何理解 JavaScript 中的 this 关键字? - 知乎