JavaScript如何具有词法作用域,如果作用域是在运行时分配的?

huangapple go评论67阅读模式
英文:

How can javascript have lexical scope if scope is assigned at runtime?

问题

我对JavaScript具有词法作用域感到困惑。

词法作用域: 词法作用域意味着在你定义函数时的作用域内的所有变量(与调用函数时相对)都在函数内部的作用域中。

但在JS中: 作用域不是在函数定义和编译时分配的,而是在运行时分配,即在函数被调用时。

在下面的示例中:如果JS具有词法作用域,我会收到一个错误。但是我没有收到错误,因为提升(hoisting)并且在运行时JS引擎检查x。

function f() {
 console.log(x);
}
const x = 10;
f(); // 10

有人能用一个示例解释一下JS如何具有词法作用域吗?谢谢!

英文:

Im confused about javascript having lexical scope.

Lexical scope: Lexical scoping means whatever variables are in scope where you define a function from (as opposed to when you call it) are in scope in the function.

However in JS its: scope isn't assigned when the function is defined and compiled rather it's assigned at runtime i.e. when the function is called

In the below example: If JS had lexical scope, I would get an error. However I do not because of hoisting and at run time js engine checks for x.

function f() {
 console.log(x);
}
const x = 10;
f(); // 10

Can someone explain with an example how JS can have lexical scope? Thanks!

答案1

得分: 2

然而,在JavaScript中,作用域并不是在函数定义和编译时分配的,而是在运行时分配的,也就是在函数被调用时分配的。

我认为你对JavaScript中作用域的描述有些混淆。对JavaScript中作用域的更准确描述可以在这篇文章中找到(重点已添加):

因为函数也是在这个时候(词法分析阶段)定义的,所以我们可以说词法作用域是基于变量和作用域块在作者编写代码时存在的位置,并且在词法分析阶段结束时被固定下来。作用域不是在运行时定义的,而是可以在运行时访问。

所以,在你的示例中:

function f() { 
  console.log(x); 
} 
const x = 10; 
f(); // 10

发生的情况是,函数f的作用域链包括:

  • 它自己的局部作用域
  • 外部的全局作用域

这个"作用域链"是在作者编写代码时(即词法作用域)定义的。

在作者编写代码时,常量x在全局作用域内定义,在调用f时,x在全局作用域内可用。函数f声明时没有定义x(但没有调用)对于这个讨论来说是无关的。

另外,关于你的代码示例,你提到"提升"是不正确的:使用const声明的变量是不会被提升的。

如果我们修改你的示例,会得到一个引用错误,因为在全局作用域中(即在作者编写代码时)调用函数f时,常量x尚未初始化(而函数f查找其作用域链,这个作用域链在作者编写代码时已经定义):

function f() { 
  console.log(x); 
} 
f(); // ReferenceError: x is not defined
const x = 10; 
英文:

> However in JS its: scope isn't assigned when the function is defined and compiled rather it's assigned at runtime i.e. when the function is called

I think you are confusing yourself with this description of scope in JS. A more accurate description of scope in JS is given by this article (emphasis added):

> Because functions are also defined at this time (lexing phase), we can say that lexical scope is based on where variables and blocks of scope exist at author time, and thus are locked down at the end of the lexing phase. Scope is not defined at runtime, rather it can be accessed at runtime.

So, in your example:

function f() { 
  console.log(x); 
} 
const x = 10; 
f(); // 10

What is happening is that the scope chain of function f consists of:

  • its local scope
  • the outer, global scope

and this "scope chain" is defined at author time (i.e. lexical scope).

At author time, the constant x is defined within the global scope, and when f is called, x is available within the global scope. That x is not defined when the function f is declared (but NOT called) is irrelevant for this discussion.

Also, you are incorrect when you mention "hoisting" regarding your code example: variables declared with const are NOT hoisted.

If we alter your example, we will get a Reference Error, since the constant x has not been initialized in the global scope (i.e. on author time), when the function f is called (and function f looks through its scope chain, which has been defined on author time):

function f() { 
  console.log(x); 
} 
f(); // 10
const x = 10; 

答案2

得分: 0

以下是翻译好的部分:

看下面的示例,函数 f 外部的所有内容都会被编译,变量会被提升。
但是函数 f 内部的内容直到调用它时才会被提升/解析。并且 f 内部的局部变量在函数内部仍然可访问(即函数的词法作用域)。

function f() {
  console.log(x);
  var a = 20;
}

const x = 10;

f(); // 10

console.log(a);
英文:

See below example, everything outside function f is compiled and vars are hoisted.
But the contents inside function f are not hoisted/parsed until it's called. And the local variables inside f remain accessible within the function (i.e. the lexical scope of function).

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function f() {
  console.log(x);
  var a = 20;
}

const x = 10;

f(); // 10


console.log(a);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月6日 19:26:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定