Javascript中的范围链

Tar*_*rik 54 javascript scope-chain

我在Javascript中阅读范围链但它对我没有任何意义,任何人都可以告诉我什么是范围链以及它如何与图形或甚至白痴都能理解的东西一起工作.我用谷歌搜索但我没有找到可理解的东西:(

提前致谢.

CMS*_*CMS 58

要了解范围链,您必须了解闭包的工作原理.

嵌套函数时会形成闭包,即使在父函数已经执行之后,内部函数也可以引用其外部封闭函数中存在的变量.

JavaScript通过遍历范围链从本地转移到全局来解析特定上下文中的标识符.

考虑具有三个嵌套函数的此示例:

var currentScope = 0; // global scope
(function () {
  var currentScope = 1, one = 'scope1';
  alert(currentScope);
  (function () {
    var currentScope = 2, two = 'scope2';
    alert(currentScope);
    (function () {
      var currentScope = 3, three = 'scope3';
      alert(currentScope);
      alert(one + two + three); // climb up the scope chain to get one and two
    }());
  }());
}());
Run Code Online (Sandbox Code Playgroud)

推荐读物:

  • @Aaron不会覆盖,但**影**. (20认同)
  • @Aaron,就像@kangax所说的那样,在*third*函数的范围内,在*second,first和global*范围内声明的`currentScope`变量将被简单地*阴影*或*隐藏*,它们的值将保持不变在外部闭包上,因为在第三个函数中,您声明了一个驻留在该范围内的**新**`currentScope`变量,当您在那里访问它时,它将是范围链中的第一个变量. (4认同)

med*_*iev 17

ECMAScript中的任何函数调用(JS所基于的核心语言)都会生成一个单独的执行上下文,它们彼此独立运行.在每个执行上下文中,this引用有问题的对象,默认为附加到函数的任何内容.

function foo() {
    alert(this===window)
}
Run Code Online (Sandbox Code Playgroud)

警告是真的,因为窗口是拥有'foo'方法的对象.函数中定义的任何变量都可以通过该函数的唯一作用域环境进行访问.

function world() {
    var name = 'global';
    alert(name)
}
Run Code Online (Sandbox Code Playgroud)

会明显提醒'全球'.

function world() {
    var name = 'global';
    (function() {
        var name = 'country';
        alert(name)
    })();
    alert(name)
}
Run Code Online (Sandbox Code Playgroud)

在最新的示例中,当调用第一个警报时,Javascript确定在内部函数的作用域链中name定义了标识符,因此它不必查找作用域链来获取它.

在第二个警报调用中,name也在同一个上下文中定义并警告"全局";

function world() {
    var name = 'global';
    (function() { alert(name) })();
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,name标识符未在同一上下文中定义,因此它必须沿作用域链向上移动到定义名称的外部函数,并且它会警告全局.

参考:


Wil*_*een 6

概括:

作用域链用于解析 JavaScript 中变量名的值。如果没有作用域链,如果在不同作用域定义了多个变量,Javascript 引擎将不知道为某个变量名称选择哪个值。javascript中的作用域链是按词法定义的,这意味着我们可以通过查看代码来了解作用域链是什么。

作用域链的顶部是全局作用域,即window浏览器中的对象(globalin NodeJS)。除了全局作用域之外,函数还有自己的变量作用域。可以通过查看定义函数的位置来确定作用域链。

解析变量时,内部函数首先查看自己的作用域。如果在自己的作用域中找不到变量,它将沿着作用域链向上查找,并在定义函数的环境中查找变量名称。这看起来像这样:

JavaScript 作用域链

因此,在我们的图像示例中,当innerFoo使用变量时bar,它首先尝试在innerFoo(函数体中的代码)的范围内找到它。然后,当它在这里找不到它时,它会沿着作用域链向上爬到foo. 其中foo也没有名为 的变量bar。因此,它将沿着作用域链向上爬,现在查看全局作用域。在全局范围内有一个名为 bar 的变量,其值为 10,bar将被解析为该变量。

例子:

let foo = 1;
let bar = 1;


function test (bar) {
   
   return function innerTestFunc () {
      let foo = 10;
      
      console.log(foo, bar);
    }
  
}

const innerTestFunc1 = test(5);
const innerTestFunc2 = test(20);


innerTestFunc1();  // logs 10, 5

innerTestFunc2();  // logs 10, 20
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我们有一个返回函数的函数。我们首先将该函数存储在变量innerTestFunc1和中innerTestFunc2。这创建了一个闭包,它基本上是外部环境作用域链的快照。

然后,当执行函数时,函数需要变量foo和 的值bar。foo 的值可以在 the 级别解析innerTestFunc,并且两者都是 10。10 已在 中找到innerFoo,因此无需攀爬 foo 的作用域链。

对于bar变量,函数无法在innerFoo. 因此,它将沿着作用域链向上爬。bar它首先遇到函数中的变量test,因此它将解析值bar为测试函数中的值(在我们的示例中为 5、20)。


Ana*_*liy 5

这是关闭.您可以在内部范围中使用范围外部的变量:

function get_inner_scope () {
    var outer = 'Outer variable value';
    return function () {
        alert(outer);
    }
}
f = get_inner_scope();
f(); // alerts Outer variable value
Run Code Online (Sandbox Code Playgroud)

通过第一个谷歌链接获得更多与其他样本相关的信息:http: //blogs.msdn.com/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx


JVM*_*JVM 5

我知道这是一个老帖子,但它对开发人员仍然有用.我想做一些不同的方式,因为初学者更容易理解范围链.这是我修改后的代码版本:

var currentScope = 0; // global scope
function a () {
   var currentScope = 1, one = 'scope1';
   alert(currentScope);

  function b () {
      var currentScope = 2, two = 'scope2';
      alert(currentScope);

      function c () {
         var currentScope = 3, three = 'scope3';
         alert(currentScope);
  alert(one + two + three); // climb up the scope chain to get one and two
     }
     c();
  }
  b();
}
a();
Run Code Online (Sandbox Code Playgroud)