Javascript / ECMAScript中函数的范围是什么?

时间:2008-10-24 21:44:45

标签: javascript functional-programming scope ecma262

今天我与同事讨论了Javascript中的嵌套函数:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

在这个例子中,试验指出b在a的体外是不可达的,就像c一样。但是,d是 - 执行a()之后。在ECMAScript v.3 standard 中查找此行为的确切定义,我没有找到我正在寻找的确切措辞;第13节第71页没有说明,是函数声明语句创建的函数对象要绑定到哪个对象。我错过了什么吗?

5 个答案:

答案 0 :(得分:22)

这是静态作用域。函数中的语句在该函数中作用域。

Javascript有一种古怪的行为,但是如果没有 var 关键字,你就暗示了一个全局变量。这就是你在考试中看到的。你的“d”变量是可用的,因为它是一个隐含的全局变量,尽管它是在函数体内写的。

另外,回答问题的第二部分:函数存在于声明的任何范围内,就像变量一样。

<强>旁注: 您可能不需要全局变量,尤其不是隐含变量。建议您始终使用var关键字,以防止混淆并保持一切清洁。

<强>旁注: ECMA标准可能不是寻找Javascript答案的最有用的地方,尽管它肯定不是一个糟糕的资源。请记住,浏览器中的javascript只是该标准的一个实现,因此标准文档将为您提供构建javascript引擎时(实际上)实现者遵循的规则。它无法提供有关您关注的实现的特定信息,即主要浏览器。特别是有几本书可以为您提供有关主要浏览器中的javascript实现如何表现的非常直接的信息。为了说明不同之处,我将在下面列出ECMAScript规范和Javascript一书的摘录。我想你会同意这本书给出更直接的答案。

这是来自 ECMAScript语言规范

  

10.2 输入执行上下文

     

每个函数和构造函数调用   甚至进入新的执行环境   如果函数调用自身   递归。每一个回报都会退出   执行上下文。抛出的异常,   如果没有抓住,也可以退出一个或   更多执行上下文。

     

控制时   进入执行上下文,范围   链创建并初始化,   执行变量实例化,   并确定该值。

     

在   范围链的初始化,   变量实例化,以及   确定这个值取决于   关于输入的代码类型。

来自 O'Reilly的Javascript: The Definitive Guide (5th Edition)

  

8.8.1词汇范围

     

JavaScript中的函数是词法上的   而不是动态范围。这个   意味着它们在范围内运行   他们被定义,而不是范围   他们被执行。当一个   函数定义,当前范围   链被保存并成为其中的一部分   函数的内部状态。   ...

道格拉斯·克罗克福德(Douglas Crockford)的书中强烈建议用于解决这些问题:

JavaScript, The Good Parts http://oreilly.com/catalog/covers/9780596517748_cat.gif

Javascript, The Good Parts,也来自O'Reilly。

答案 1 :(得分:4)

据我所知,就范围界定而言,这些是等价的:

function a() { ... }

var a = function() { ... }

答案 2 :(得分:2)

值得注意的是,当d被创建为“全局”时,它实际上是作为窗口对象的属性创建的。这意味着您可能无意中覆盖了窗口对象上已存在的内容,或者您​​的变量实际上可能根本无法创建。所以:

function a() {
    d = 'Hello World';
}
alert(window.d); // shows 'Hello World'

但你不能这样做:

function a() {
    document = 'something';
}

因为你无法覆盖window.document对象。

出于所有实际目的,您可以成像所有代码都在巨大的with(window)块中运行。

答案 3 :(得分:1)

Javascript有两个范围。全球性和功能性。如果使用“var”关键字在函数内声明变量,它将是该函数的本地变量,以及任何内部函数。如果在函数之外声明变量,则它具有全局范围。

最后,如果在首次声明变量时省略var关键字,则javascript假定您需要一个全局变量,无论您在何处声明它

所以,你正在调用函数a,函数a正在声明一个全局变量d。

答案 4 :(得分:0)

...

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

没有前面的 var ,d是全局的。这样做是为了私有:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   var d = 'Bound to local object.'
}