Ben*_*Ben 4 javascript ecmascript-6
为什么要将o.foo()全局对象打印到控制台?
let o = {
foo: () => console.log(this),
bar() { console.log(this); }
};
o.foo(); // Global object / undefined
o.bar(); // o
Run Code Online (Sandbox Code Playgroud)
我认为箭头函数的等价物可能是这样的(但它不是):
let o = {
foo: function() {
var self = this;
console.log(self);
},
bar() {?
console.log(this);
}
};
o.foo(); // o
o.bar(); // o
Run Code Online (Sandbox Code Playgroud)
箭功能保留在this了的周围执行上下文从他们被宣布时.它们并不this像常规方法那样一直在变化.
在您的示例中,没有执行上下文foo,因此this也是如此undefined.这与function在相同范围内使用关键字声明的函数的行为相同,并以相同的方式调用.您可以使用以下方法测试:
let foo = () => { return this; }
console.log(foo() === undefined);
Run Code Online (Sandbox Code Playgroud)
根据14.2.16的规格:
在ArrowFunction中对arguments,super或this的任何引用都必须解析为词法封闭环境中的绑定.通常,这将是直接封闭函数的函数环境.
(强调我的)
有趣的是,当该箭头函数出现在全局范围内时,BabelJS转换器只是输出
"use strict";
var foo = function foo() {
return undefined;
};
Run Code Online (Sandbox Code Playgroud)
好像这是唯一正确的行为.阅读规范,它似乎并不严格,但这似乎是正确的做法.
如果您设法使用没有模块的箭头运行ES6代码,那么您最终可以使用全局对象.根据10.2.1的规格:
- 全局代码是严格模式代码,如果它以包含使用严格指令的指令序言开头(见14.1.1).
- 模块代码始终是严格的模式代码.
因此可以在非严格的上下文中获取ES6代码.如果发生这种情况,那么this将使用经典回退并设置为window(在9.2中作为未定义的规范[[ThisMode]]).
在这个例子中,没有立即封闭的函数,因此没有词汇范围可以拾取,因此this最终未定义.
在第二个示例中,捕获this并没有什么区别:
let o = {
foo: function() {
var self = this;
console.log(self);
},
bar() {?
console.log(this);
}
};
Run Code Online (Sandbox Code Playgroud)
该var self语句在函数内,因此它不会执行任何操作.如果你这样做:
let o = {
foo: function() {
var self = this;
return function() {
console.log(self);
}
}(),
bar() {?
console.log(this);
}
};
Run Code Online (Sandbox Code Playgroud)
然后它会有你期望的行为(粗略地),虽然this仍然是未定义的(或全局对象),因为你不在被捕获的词汇环境中.
如果你要使用
class Foo {
bar() {
let baz = () => { return this; }
}
}
Run Code Online (Sandbox Code Playgroud)
那么bar可以归结为
function bar() {
var _this = this;
var baz = function baz() {
return _this;
};
}
Run Code Online (Sandbox Code Playgroud)
哪能做到你想要的.这只能起作用,因为有一个周围的上下文要捕获.