Javascript 执行堆栈与范围链

Javascript 执行堆栈与范围链,javascript,Javascript,我读过的文章说,当调用函数时,会向堆栈中添加一个新的执行上下文,并通过向上遍历堆栈来创建范围链。但这肯定会导致3在上述代码中被警告吗 它是如何计算范围链的?范围链由范围的词汇嵌套决定。范围可以动态地受到影响(通过和),但这会导致很多问题。当前的函数激活堆栈肯定与作用域无关,您正在创建仅存在于立即调用函数表达式(IIFE)范围内的局部变量 在该范围内定义的任何函数都可以访问变量i one()。它正在查找其作用域链到不存在的window.i。调用堆栈和执行上下文堆栈不相同。函数调用会向调用堆栈添加一

我读过的文章说,当调用函数时,会向堆栈中添加一个新的执行上下文,并通过向上遍历堆栈来创建范围链。但这肯定会导致3在上述代码中被警告吗


它是如何计算范围链的?

范围链由范围的词汇嵌套决定。范围可以动态地受到影响(通过
),但这会导致很多问题。当前的函数激活堆栈肯定与作用域无关,您正在创建仅存在于立即调用函数表达式(IIFE)范围内的局部变量

在该范围内定义的任何函数都可以访问变量
i


one()。它正在查找其作用域链到不存在的
window.i

调用堆栈和执行上下文堆栈不相同。函数调用会向调用堆栈添加一个级别,但不会更改执行上下文堆栈。但是,您调用的函数具有不同的执行上下文堆栈

每个函数作用域都有自己的执行上下文堆栈,这取决于函数的创建位置,而不是从调用代码继承执行上下文堆栈

如果函数彼此嵌套,并且只调用内部函数(如页面上的第一个示例所示),则调用堆栈和执行上下文堆栈将恰好对应。

调用堆栈(如前所述,在调用函数时不断向堆栈顶部添加执行上下文)和词法范围(允许从外部范围访问变量)彼此独立

词法作用域仅取决于函数的创建位置,而不取决于函数的调用位置,因此在您的示例中,函数“二”是在函数“一”内创建的,因此当函数“二”内的变量“i”试图访问“i”时,它会先在自己的作用域中找到“i”,因为没有“i”定义它将进入在您的案例中创建函数的作用域,它的函数“2”(不是在下面匿名IIFE中调用函数的位置),并且它无法在函数“2”中再次找到变量“i”,现在因为函数“2”是在全局作用域(默认执行上下文)中定义的,JS将尝试查找“i”的值在导致“未定义”的全局范围内

为了访问变量“i”,您需要将函数“2”移动到匿名IIFE中,如下所示,函数2具有函数“1”的外部词法范围,函数“1”具有匿名IIFE的外部词法范围,该匿名IIFE的外部词法范围已分配给3,并发出警报

function one() {
    function two() {
        alert(i);
    }
    return two; 
}

(function() {
    var i = 3;

    var f = one();

    f(); // Uncaught ReferenceError: i is not defined
}());

希望这一点现在清楚了:)

您到底有什么问题?您在哪里读到范围链是通过向上遍历堆栈创建的?那是不对的。啊,好吧,那个作者说的是词汇上的“亲子关系”。这不是函数调用堆栈,而是函数序列嵌套在代码中的事实。在任何给定的执行点,都有一个当前上下文,对作用域来说,重要的是当前代码出现在源结构中的位置—如何以及在其他作用域中的嵌套位置。调用堆栈不会影响这一点。很棒的文章。。。但函数的执行上下文只有在被调用时才添加到执行上下文堆栈的顶部。那么,它们不应该总是对应吗?你能提供一些他们不会的例子吗?
(function () {
  var i = 3;
function one() {
  function two() {
    alert(i); // will alert 3
  }
  return two;
}
var f = one();
f();
}());