Javascript 箭头功能-为什么要将全局对象打印到控制台?
为什么Javascript 箭头功能-为什么要将全局对象打印到控制台?,javascript,ecmascript-6,Javascript,Ecmascript 6,为什么o.foo()会将全局对象打印到控制台 let o = { foo: () => console.log(this), bar() { console.log(this); } }; o.foo(); // Global object / undefined o.bar(); // o 我认为箭头函数的等价物可能是这样的(但事实并非如此): 箭头函数保留声明时周围环境的此。它们不会像普通方法一样,一直改变这个 在您的示例中,没有围绕foo的执行上下文,因此此是未定义的。这
o.foo()
会将全局对象打印到控制台
let o = {
foo: () => console.log(this),
bar() { console.log(this); }
};
o.foo(); // Global object / undefined
o.bar(); // o
我认为箭头函数的等价物可能是这样的(但事实并非如此):
箭头函数保留声明时周围环境的此
。它们不会像普通方法一样,一直改变这个
在您的示例中,没有围绕foo
的执行上下文,因此此
是未定义的
。这与在相同范围内使用function
关键字声明并以相同方式调用的函数的行为相同。您可以通过以下方式进行测试:
let foo = () => { return this; }
console.log(foo() === undefined);
发件人:
ArrowFunction中对参数、super或this的任何引用都必须解析为词汇封闭环境中的绑定。通常,这将是一个直接封闭函数的函数环境
(强调矿山)
有趣的是,当该箭头函数出现在全局范围中时,只需输出
"use strict";
var foo = function foo() {
return undefined;
};
好像那是唯一正确的行为。阅读规范时,它似乎没有那么严格,但这似乎是正确的做法
如果您在没有模块的情况下使用箭头运行ES6代码,那么最终可能会得到这样的全局对象。Per:
- 如果全局代码以包含Use strict指令的指令序言开头,则它是严格模式代码(参见14.1.1)
- 模块代码始终是严格的模式代码
因此,在非严格上下文中获取ES6代码是可能的。如果发生这种情况,此
将使用经典回退,并设置为窗口
(作为未定义的[[ThisMode]]
)
在本例中,没有直接封闭函数,因此没有词汇范围可供选择,因此此
最终未定义
在第二个示例中,此
上的捕获没有任何区别:
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);
}
};
然后它将具有您期望的行为(大致上),尽管此
仍将是未定义的(或全局对象),因为您不在要捕获的词汇环境中
如果你要用
class Foo {
bar() {
let baz = () => { return this; }
}
}
然后,条
可以传输到
function bar() {
var _this = this;
var baz = function baz() {
return _this;
};
}
这正是你想要的。这仅仅是因为需要捕获周围的上下文。“在本例中,没有直接封闭的函数,因此没有词汇范围可供选择,因此这最终是未定义的。”……或者全局对象处于草率模式?我认为“函数范围”在规范中不是一个定义良好的术语。您的意思是[[Environment]]
internal property?我无法在我的机器上重现第二个行为,但这可能是因为Babel只是简单地将let foo=()=>{return this;}
直接传输到var foo=function foo(){return undefined;}代码>(不是开玩笑)。这使我认为这是一个足够好的定义行为,可以依赖。用正确的术语替换“函数范围”,并添加了关于第二个示例的一些信息。FWIW,bable将此
转换为未定义的
,因为它假定每个文件都是一个模块。模块总是严格的,它们的此
值总是未定义
如果在脚本的顶层声明了arrow函数,则此
将引用窗口
。我假设您从。请注意最大的区别:我在arrow函数外部声明了self
,您在arrow函数内部声明了它。这不是它的工作原理。等价物为var self=this;设o={foo:console.log(self);}代码>@FelixKling是的。谢谢你澄清这一点。这是我的误解(我写下问题后意识到)。
function bar() {
var _this = this;
var baz = function baz() {
return _this;
};
}