箭头功能 - 为什么将全局对象打印到控制台?
Arrow functions - why does this print the global object to the console?
为什么 o.foo()
将全局对象打印到控制台?
let o = {
foo: () => console.log(this),
bar() { console.log(this); }
};
o.foo(); // Global object / undefined
o.bar(); // o
我认为箭头函数的等价物可能是这样的(但不是):
let o = {
foo: function() {
console.log(this);
},
bar() {
console.log(this);
}
};
o.foo(); // o
o.bar(); // o
箭头函数保留 周围execution context 的this
从它们被声明时起。它们不会像正常方法那样一直更改 this
。
在您的示例中,foo
周围没有执行上下文,因此 this
是 undefined
。这与在相同范围内使用 function
关键字声明并以相同方式调用的函数具有相同的行为。您可以使用以下方法进行测试:
let foo = () => { return this; }
console.log(foo() === undefined);
Any reference to arguments, super, or this within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.
(强调我的)
有趣的是,当箭头函数出现在全局范围内时,the BabelJS transpiler 只是输出
"use strict";
var foo = function foo() {
return undefined;
};
好像那是唯一正确的行为。阅读规范,它似乎并不那么严格,但这似乎是正确的做法。
如果您设法运行 ES6 代码使用不带模块的箭头,那么您似乎可以像这样结束全局对象。每 the spec at 10.2.1:
- Global code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive (see 14.1.1).
- Module code is always strict mode code.
因此有可能在非严格上下文中获取 ES6 代码。如果发生这种情况,那么 this
将使用经典回退并设置为 window
(在 the spec at 9.2 中作为未定义的 [[ThisMode]]
)。
在这个例子中,没有立即封闭的函数,因此没有词法范围可供选择,所以 this
最终未定义。
在您的第二个示例中,this
上的捕获没有任何区别:
let o = {
foo: function() {
var self = this;
console.log(self);
},
bar() {
console.log(this);
}
};
var self
语句在函数内,所以它不会做任何事情。如果你要这样做:
let o = {
foo: function() {
var self = this;
return function() {
console.log(self);
}
}(),
bar() {
console.log(this);
}
};
那么它将具有您期望的行为(大致),尽管 this
仍然是未定义的(或全局对象),因为您不在要捕获的词法环境中。
如果你要使用
class Foo {
bar() {
let baz = () => { return this; }
}
}
然后 bar
可以转译为
function bar() {
var _this = this;
var baz = function baz() {
return _this;
};
}
它可以满足您的需求。这之所以有效,是因为要捕获周围的上下文。
为什么 o.foo()
将全局对象打印到控制台?
let o = {
foo: () => console.log(this),
bar() { console.log(this); }
};
o.foo(); // Global object / undefined
o.bar(); // o
我认为箭头函数的等价物可能是这样的(但不是):
let o = {
foo: function() {
console.log(this);
},
bar() {
console.log(this);
}
};
o.foo(); // o
o.bar(); // o
箭头函数保留 周围execution context 的this
从它们被声明时起。它们不会像正常方法那样一直更改 this
。
在您的示例中,foo
周围没有执行上下文,因此 this
是 undefined
。这与在相同范围内使用 function
关键字声明并以相同方式调用的函数具有相同的行为。您可以使用以下方法进行测试:
let foo = () => { return this; }
console.log(foo() === undefined);
Any reference to arguments, super, or this within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.
(强调我的)
有趣的是,当箭头函数出现在全局范围内时,the BabelJS transpiler 只是输出
"use strict";
var foo = function foo() {
return undefined;
};
好像那是唯一正确的行为。阅读规范,它似乎并不那么严格,但这似乎是正确的做法。
如果您设法运行 ES6 代码使用不带模块的箭头,那么您似乎可以像这样结束全局对象。每 the spec at 10.2.1:
- Global code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive (see 14.1.1).
- Module code is always strict mode code.
因此有可能在非严格上下文中获取 ES6 代码。如果发生这种情况,那么 this
将使用经典回退并设置为 window
(在 the spec at 9.2 中作为未定义的 [[ThisMode]]
)。
在这个例子中,没有立即封闭的函数,因此没有词法范围可供选择,所以 this
最终未定义。
在您的第二个示例中,this
上的捕获没有任何区别:
let o = {
foo: function() {
var self = this;
console.log(self);
},
bar() {
console.log(this);
}
};
var self
语句在函数内,所以它不会做任何事情。如果你要这样做:
let o = {
foo: function() {
var self = this;
return function() {
console.log(self);
}
}(),
bar() {
console.log(this);
}
};
那么它将具有您期望的行为(大致),尽管 this
仍然是未定义的(或全局对象),因为您不在要捕获的词法环境中。
如果你要使用
class Foo {
bar() {
let baz = () => { return this; }
}
}
然后 bar
可以转译为
function bar() {
var _this = this;
var baz = function baz() {
return _this;
};
}
它可以满足您的需求。这之所以有效,是因为要捕获周围的上下文。