Javascript作用域链
我读了很多关于javascript作用域链的文章,我认为我对它有相当的了解。然而,一个非常简单的练习让我意识到我还没有完全理解它 我创建了以下代码Javascript作用域链,javascript,scope,executioncontext,Javascript,Scope,Executioncontext,我读了很多关于javascript作用域链的文章,我认为我对它有相当的了解。然而,一个非常简单的练习让我意识到我还没有完全理解它 我创建了以下代码 function foo () { var b = 2; bar() } function bar () { console.log(b); } foo(); 此代码给出了一个引用错误。但是,我假设它仍然会打印出2。我的理由如下: foo和bar的函数声明 执行Foo时,将创建一个新的执行上下文。Foo的内部属性[[Sco
function foo () {
var b = 2;
bar()
}
function bar () {
console.log(b);
}
foo();
此代码给出了一个引用错误。但是,我假设它仍然会打印出2。我的理由如下:
- foo和bar的函数声明
- 执行Foo时,将创建一个新的执行上下文。Foo的内部属性[[Scope]设置为全局
- var b已吊装
- 变量b被分配为2
- bar是在foo执行上下文中执行的。因此,我假设bar函数的内部属性[[Scope]]将设置为foo
- b未在功能栏中定义,因此将查找scopechain并找到值b=2
- 控制台日志(2)
b
是在foo
的作用域中定义的
bar
是从foo
的范围调用的,是的,但它是在foo
的范围之外定义的。这意味着bar
无法访问b
图像通常有助于:
将每个红方块视为一个“范围”。foo
和bar
共享外部范围,但它们不能访问彼此的内部范围。b
在foo
的范围中定义
bar
是从foo
的范围调用的,是的,但它是在foo
的范围之外定义的。这意味着bar
无法访问b
图像通常有助于:
将每个红方块视为一个“范围”。
foo
和bar
共享外部范围,但它们不能访问彼此的内部范围。让我以不同的方式编写代码,以说明范围
var scope = {};
scope.foo = function() {
var b = 2;
scope.bar()
}
scope.bar = function() {
// this will look for a property 'b' defined in the bar method, but it doesn's exist
console.log(b);
// changing the console.log call to match the changes made above, means it will
// look like this
console.log(scope.b)
// but now scope.b is also not defined
}
scope.foo();
换句话说,当您尝试访问“bar”中的“b”时,它将在创建“bar”的范围内搜索它,而不是在调用“bar”的范围内搜索它。让我以不同的方式编写代码,以说明该范围
var scope = {};
scope.foo = function() {
var b = 2;
scope.bar()
}
scope.bar = function() {
// this will look for a property 'b' defined in the bar method, but it doesn's exist
console.log(b);
// changing the console.log call to match the changes made above, means it will
// look like this
console.log(scope.b)
// but now scope.b is also not defined
}
scope.foo();
换句话说,当您尝试访问“bar”中的“b”时,它将在创建“bar”的范围内搜索它,而不是在调用“bar”的范围内搜索它。Cerburs感谢您的快速响应。让我困惑的部分是stackoverflow中提出的这个问题。您描述它的方式,在我看来,范围链是由声明函数的执行上下文决定,即其词汇环境,而不是由调用函数的执行上下文决定。然而,链接问题的答案似乎暗示了后者?@JackSpar:我不确定该答案的最后一行是什么意思。没有示例就很难说了。有一件事我确信,
b
是不可访问的,因为它在foo
的范围内。好的,那我想我理解你了。只是为了确认我的理解。下面的代码不会被认为是一个闭包(程序员通常谈论它的方式)因为函数baz应该已经可以访问函数foo的作用域了,正如它在那里定义/声明的那样?@JackSpar:这是有效的,因为baz
是在a
所在的同一作用域中定义的。你也可以从全局作用域公开baz
,并且仍然让它记录a
:function foo(){var a=2;function baz(){console.log(a);}return baz;}var alias=foo();alias()
完美!非常感谢:)Cerburs感谢您的快速响应。让我困惑的是关于stackoverflow的问题。您描述它的方式,在我看来,作用域链是由声明函数的执行上下文决定的,即它的词法环境,而不是由h调用函数的执行上下文。然而,链接问题的答案似乎暗示了后者?@JackSpar:我不确定该答案中的最后一行是什么意思。没有一个例子就很难说。我确信的一件事是,b
无法访问,因为它在foo
的范围内。好的,那我就不知道了hink我理解你。只是为了确认我的理解。下面的代码不会被认为是一个闭包(程序员通常谈论它的方式)因为函数baz应该已经可以访问函数foo的作用域了,正如它在那里定义/声明的那样?@JackSpar:这是有效的,因为baz
是在a
所在的同一作用域中定义的。你也可以从全局作用域公开baz
,并且仍然让它记录a
:function foo(){var a=2;function baz(){console.log(a);}return baz;}var alias=foo();alias();
Perfect!非常感谢:)这确实有助于可视化范围:-)这确实有助于可视化范围:-)