如何使用 "strict" 和 "non-strict" 模式确定常规箭头 fn 内的正确“this”?
How to determine the correct `this` inside a regular arrow fn with "strict" and "non-strict" mode?
对于下面的代码片段
案例 1:严格模式
"use strict"
let obj = {
method: function(){
console.log(this);
},
arrowMethod: () => {
console.log(this);
}
};
obj.method(); // call 1
obj.arrowMethod(); // call 2
let method = obj.method;
let arrowMethod = obj.arrowMethod;
method(); // call 3
arrowMethod(); // call 4
输出为:
{method: ƒ, arrowMethod: ƒ}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
undefined
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
情况 2:非严格模式
将输出相同的代码段
{method: ƒ, arrowMethod: ƒ}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
我的理解是:
在严格模式下,
call 1
- 当函数作为对象的方法被调用时,this 被设置为调用该方法的对象。
call 2
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。
call 3
- 如果在进入执行上下文时未设置此值,则它保持未定义状态。
call 4
不管怎样,arrowMethod 的 this 设置为创建时的状态(在上面的示例中,全局对象)。
在非严格模式下,
call 1
- 当函数作为对象的方法被调用时,this 被设置为调用该方法的对象。
call 2
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。
call 3
- 由于代码不是在严格模式下,并且因为 this 的值不是由调用设置的,所以 this 将默认为全局对象,它是一个 window一个浏览器。
call 4
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。
问题
不像Case 1: Strict mode
中的call 4
,因为它的值在创建箭头fn时没有设置,它一直保持未定义状态?
or
是否严格模式不适用于箭头 fns,因此在创建箭头 fn 时,this 设置为 window 对象?
是的,不默认从 undefined
到全局对象的严格模式函数的规则不适用于箭头函数,因为它们根本没有自己的 this
。它始终是来自外部范围的 this
值。在你的例子中就是 window
。
可能重要的是它们定义的函数是否使用严格模式,因为这是箭头函数从中获取其值的地方:
function strictMake() {
"use strict";
return () => { console.log(this == window); };
}
function sloppyMake() {
return () => { console.log(this == window); };
}
const arrowFromStrict = strictMake();
const arrowFromSloppy = sloppyMake();
arrowFromStrict();
arrowFromSloppy();
对于下面的代码片段
案例 1:严格模式
"use strict"
let obj = {
method: function(){
console.log(this);
},
arrowMethod: () => {
console.log(this);
}
};
obj.method(); // call 1
obj.arrowMethod(); // call 2
let method = obj.method;
let arrowMethod = obj.arrowMethod;
method(); // call 3
arrowMethod(); // call 4
输出为:
{method: ƒ, arrowMethod: ƒ}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
undefined
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
情况 2:非严格模式
将输出相同的代码段
{method: ƒ, arrowMethod: ƒ}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
Window {parent: Window, opener: null, top: Window, length: 1, frames: Window, …}
我的理解是:
在严格模式下,
call 1
- 当函数作为对象的方法被调用时,this 被设置为调用该方法的对象。call 2
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。call 3
- 如果在进入执行上下文时未设置此值,则它保持未定义状态。call 4
不管怎样,arrowMethod 的 this 设置为创建时的状态(在上面的示例中,全局对象)。
在非严格模式下,
call 1
- 当函数作为对象的方法被调用时,this 被设置为调用该方法的对象。call 2
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。call 3
- 由于代码不是在严格模式下,并且因为 this 的值不是由调用设置的,所以 this 将默认为全局对象,它是一个 window一个浏览器。call 4
- 不管怎样,arrowMethod 的 this 被设置为创建时的状态(在上面的示例中,全局对象)。
问题
不像
Case 1: Strict mode
中的call 4
,因为它的值在创建箭头fn时没有设置,它一直保持未定义状态?or
是否严格模式不适用于箭头 fns,因此在创建箭头 fn 时,this 设置为 window 对象?
是的,不默认从 undefined
到全局对象的严格模式函数的规则不适用于箭头函数,因为它们根本没有自己的 this
。它始终是来自外部范围的 this
值。在你的例子中就是 window
。
可能重要的是它们定义的函数是否使用严格模式,因为这是箭头函数从中获取其值的地方:
function strictMake() {
"use strict";
return () => { console.log(this == window); };
}
function sloppyMake() {
return () => { console.log(this == window); };
}
const arrowFromStrict = strictMake();
const arrowFromSloppy = sloppyMake();
arrowFromStrict();
arrowFromSloppy();