2
# Version A - Function Declaration Statement

// Some JavaScript code
function a() {
    // code within function
}
//Some more JavaScript code


# Version B - Function Expression

// Some JavaScript code
var b = function () {
    // code within function
};
// Some more JavaScript code

我一直在阅读 JavaScript:权威指南,我想确保我了解 JavaScript 如何处理这两个版本。我将在下面解释我对每个版本的理解:

版本 A

  1. JavaScript 在全局范围内扫描脚本并识别所有变量和函数定义并将它们提升到顶部。变量赋值和函数评估还不会发生。
  2. 对于函数 a(),JavaScript 会打包全局上下文并将其与函数的作用域链相关联。此时,函数 a() 将知道步骤 1 中的所有变量和函数定义。
  3. JavaScript 不会评估函数 a(),因此对函数内的本地上下文一无所知。在调用该函数之前,这将保持不变。

版本 B

  1. 与上面的步骤 1 相同 - JavaScript 在全局范围内扫描脚本并识别所有变量和函数定义并将它们提升到顶部。因为变量 b 被提升到顶部,所以脚本等价于:

    var b;
    // Some JavaScript code
    b = function (){ /* code within function */ };
    // Some more JavaScript code
    
  2. 当 JavaScript 处理变量 b 的赋值时,它看到正在定义一个匿名函数对象。JavaScript 在定义函数时,会将定义函数的上下文(在本例中为全局上下文)打包,并将其与函数的作用域链相关联。此时,匿名函数将知道步骤 1 中的所有变量和函数定义,其中包括未定义的 var b。

  3. 因为 JavaScript 看到函数被用作变量赋值中的表达式,所以它将评估函数表达式。当它对函数表达式求值时,它会再次将本地范围内的所有变量和函数定义提升到顶部,如果此函数表达式中有任何函数声明语句,它将打包此本地上下文并将其添加到范围链中这个功能的。
  4. 计算函数时返回一个函数对象,然后将函数对象分配给 var b。

如果您可以对每个版本发表评论并让我知道我的理解是否准确,那就太好了。

4

1 回答 1

0

理论很好,但在现实生活中浏览器使用自己的方言(由于使用自己的引擎并添加了浏览器糖果)。

例如,IE 并不关心您的脚本标签是否指定了“文本/javascript”。无论如何,它都会使用自己的 JScript。

因此(为了设计一种多语言的 EcmaScript 方言),还有助于理解该理论在现实生活中可能不会以同样的方式起作用。

例如,命名函数表达式被视为 BOTH——IE(JScript) 中的函数声明和函数表达式:

typeof g; // "function"
var f = function g(){};

有关其中一些示例,请参阅此链接:http:
//kangax.github.com/nfe/#jscript-bugs

实际上,这是一个相当完整的“半官方”(来自 MS 的 Pratap Lakshman)概述 JScript 与 ES3 的偏差:
http ://wiki.ecmascript.org/lib/exe/fetch.php?media=resources:jscriptdeviationsfromes3 .pdf

最后,我想指出这个非常有用的视频,Douglas Crockford 在“Crockford on JavaScript - Act III: Function the Ultimate”中解释了一些更彻底的事情:http:
//youtu.be/ya4UHuXNygM

希望这可以帮助!

于 2013-03-27T18:14:16.280 回答