Javascript中的声明性环境记录和作用域



我目前正在学习Javascript范围,并尝试为正在发生的事情制定一些规则。但每次意外的行为都会让他们崩溃。所以我需要帮助。

考虑以下示例

console.log("v" in this);    //true
console.log(v)     //undefined
{
{
function a() {
1;
}
}
{
function a() {
2;
}
{
function v() {
3;
}
}
}
}
console.log(a);    //ƒ a() {2}

函数v在内存中,但我无法在第2行使用它。但在这个例子中,我可以。

console.log(v);
{
function v() {
1;
}
}

我对编译器在执行脚本之前所做的规则以及评估声明的步骤(顺序(感到困惑,包括使用let、const、var以及函数声明和宣言的语句。我读过关于作用域的博客和书籍,但几乎所有这些都将变量、函数和类视为独立的东西,而不是作用域的D.E.R中附带的属性

函数v在内存中,但我无法在第2行使用它。但在这个例子中,我可以

不,两个示例的行为方式相同。在这两种情况下,v都是在块内声明的,在这两个情况下,它的值都是undefined

在松散模式(也称为"草率"模式(中,块中符合特定条件的函数声明会在函数(或全局(范围内而不是块范围内创建一个提升绑定(在本例中为v(。该绑定是用值undefined初始化的;直到在代码的逐步执行中达到声明,它才获得分配给它的函数。还有一个块本地绑定,它为函数/全局绑定提供阴影,该绑定在块的开头用函数初始化。是的,这是非常令人困惑的;这是因为这是在将ES2015中的规则追溯应用于浏览器引擎中的通用功能子集,这些引擎使用块声明的函数(不在规范中,但是允许的扩展(扩展了JavaScript。

但是,不要依赖它,甚至不要真的麻烦将它提交到内存中。这是传统的兼容性。

相反,使用严格模式,在这种模式下,声明成为块的本地声明(在块内完全提升(,并且在块外根本不能使用v

"use strict";
console.log("v" in this);    // false
console.log(v)               // ReferenceError
{
{
function a() {
1;
}
}
{
function a() {
2;
}
{
function v() {
3;
}
}
}
}
console.log(a);

最新更新