可变吊装

时间:2010-09-16 10:00:40

标签: javascript hoisting

alert(myVar1);
return false;
var myVar1;

上面的代码在IE,FF和Opera中抛出错误,指出return语句必须进入函数。但它在Safari和Chrome中有效(显示undefined)。

以上代码已在全球范围内编写。在所有功能之外。

任何原因?

5 个答案:

答案 0 :(得分:35)

在javaScript中,变量被移动到脚本的顶部,然后运行。所以当你运行它时会做

var myVar1;
alert(myVar1);
return false;

这是因为javascript确实没有真正意义上的词汇范围。这就是为什么它被认为是最好的做法,将所有变量声明在该区域的顶部,它们将用于防止吊装导致问题。 JSLint会抱怨这个。

这是一篇很好的文章解释它http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

退货无效。如果你想做一个真正的提升示例(取自上面的链接),请执行

var foo = 1; 
function bar() { 
    if (!foo) { 
        var foo = 10; 
    } 
    alert(foo); 
} 
bar();

这将提醒10

评论后编辑

以下是我的理解,我已经在某处读过,但找不到我读过的所有资料,所以我愿意接受更正。

此警告归功于JavaScript JIT的差异。 TraceMonkey(http://ejohn.org/blog/tracemonkey/)我相信会接受JavaScript并进行快速静态分析,然后执行JIT然后尝试运行它。如果失败那么显然没有任何作用。

V8不进行静态分析,然后移动到JIT然后运行。它更类似于python。如果你在Chrome的开发者控制台中运行脚本(在Windows中按ctrl + shift + j),它会抛出一个错误,但也会运行以提醒你。

答案 1 :(得分:17)

有时候提升会以一种可能给人留下错误印象的方式解释,即变量和函数被JavaScript引擎提升,好像它们被物理移动到顶部,这实际上并不正确,如下面的代码所示: p>

console.log(a);
var a = 'Hello World!';

我们在控制台上看到的是undefined,而不是'Hello World',因此我们得到了以下代码的行为

var a;
console.log(a);
a = 'Hello World!';

不是

的行为
var a = 'Hello World!';
console.log(a);

您可以从变量和函数声明移到top语句中获得印象。

但JavaScript实际上并没有将代码移动到任何地方。您需要了解JavaScript中的执行上下文。它有两个阶段的创建阶段和执行阶段。在创建阶段,为这些变量和函数创建了内存空间,人们似乎将此步骤与提升相混淆。 JavaScript实际上并没有将代码移动到任何地方,所发生的是JavaScript为您的所有代码创建了内存空间,即变量和函数,函数可以完全放在内存中,但是在变量的情况下,分配在执行上下文的执行阶段处理。因此,当你执行var a = 'Hello World!'时,JavaScript引擎在执行上下文的执行阶段开始执行它时知道a的值,因此它将未定义占位符,并且所有变量最初都设置为undefined in JavaScript的。所以依靠吊装并看到未定义是不好的。因此,在代码之上声明变量和函数总是好的。

答案 2 :(得分:11)

ECMA-262第3版第12.9节(第75页)指出:

  

如果ECMAScript程序包含不在 FunctionBody 中的return语句,则认为它在语法上不正确。

也就是说,函数外部的return语法错误。如果发生语法错误,则不会运行任何代码。想想你的例子就像你写的那样:

alert(myVar1);
return false;
syntax error))))))))))))))))));

此外,第16节(第157页)指出:

  

实现可能会将以下类型的运行时错误的任何实例视为语法错误,因此也是如此   及早报告:

     
      
  • 不正确地使用return,break和continue。
  •   

Firefox的引擎等。人。 (即允许return在全局范围内的那些JavaScript实现)可能符合,假设以下子句(在同一部分中)允许return的实现定义全球范围:

  

实施应报告指定的所有错误,但以下情况除外:

     
      
  • 实现可以提供除本说明书中描述的那些之外的其他类型,值,对象,属性和功能。这可能导致构造(例如在全局范围内查找变量)具有实现定义的行为而不是抛出错误(例如 ReferenceError )。
  •   

答案 3 :(得分:3)

这段代码没什么意义:

  • 永远不会运行var myVar1
  • 由于您不在某个功能中,return false;不会返回任何内容

Opera,IE和FF是正确的,因为这个代码实际上无效,因为除非你在函数中,否则你无法返回。

如果它在Safari和Chrome中有效,那一定是因为他们使用的javascript引擎已准备好处理错误的代码。我的猜测是,他们会看到“return”并将其删除或替换为某种break

有关功能的更多信息:http://www.w3schools.com/js/js_functions.asp

答案 4 :(得分:0)

这是JavaScript吊装的事情,换句话说,我们正在尝试打印变量的值,它没有任何值

Javascript会将上述代码呈现为: -



var myVar1
alert (myVar1)
return false




为了澄清更多我提到链接javascript hoisting:http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html