为啥返回后变量提升在某些浏览器上有效,而在某些浏览器上无效?

Posted

技术标签:

【中文标题】为啥返回后变量提升在某些浏览器上有效,而在某些浏览器上无效?【英文标题】:Why variable hoisting after return works on some browsers, and some not?为什么返回后变量提升在某些浏览器上有效,而在某些浏览器上无效? 【发布时间】:2011-04-13 03:18:12 【问题描述】:
alert(myVar1);
return false;
var myVar1;

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

上面的代码是在全局范围内编写的。在所有功能之外。

有什么原因吗?

【问题讨论】:

我很害怕,很困惑,也有点好奇……你想帮什么忙? @Hahsen,我只是想了解各种可用的浏览器和 javascript 陷阱。这是变量提升,我试图理解它在全局范围内的行为以及返回语句。虽然不在函数定义中时不允许返回,但代码仍然可以在 chrome 和 safari 中运行。我正在尝试找出原因 把它理解为变量和声明预处理可能更容易理解。声明不会移动(或“提升到顶部”),它们会在执行任何代码之前进行处理。阅读 ECMA—262 §10.3 了解进入执行上下文时会发生什么,这很容易理解。 【参考方案1】:

在 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)中运行脚本,它会抛出错误,但也会运行以向您发出警报。

【讨论】:

@Automater Tester,您的代码完全正确,它是 javascript 中提升的一个非常好的示例。但我想知道的是为什么 return 没有在 chrome 和 safari 中抛出错误 @alter 我已经为你添加了更多信息。 "在 javaScript 中的变量被移动到脚本的顶部然后运行。"实际上,变量 names(而不是赋值/定义)被“提升”到包含范围的顶部(以最近的为准;if et. al. do not在这个意义上创建一个“范围”)。 @strager 你是对的,只有名字被提升了。当我输入“然后运行”时,我的意思是整个脚本。 小心使用新的 ES6 JavaScript 特性。用 const/let 声明的变量不再被提升(是的,这个语句有点简化)。详解:***.com/q/31219420/3242070【参考方案2】:

有时对提升的解释可能会产生错误的印象,即变量和函数被 JavaScript 引擎提升,就好像它们被物理移动到顶部一样,这实际上是不正确的,如下面的代码所示:

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);

你可能会从变量和函数声明被移到顶部语句中得到印象。

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

【讨论】:

【参考方案3】:

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)。

【讨论】:

【参考方案4】:

这段代码没什么意义:

var myVar1 永远不会运行。 return false; 不会返回任何东西,因为您不在函数中

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

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

更多函数信息:http://www.w3schools.com/js/js_functions.asp

【讨论】:

当我在函数外使用 return 语句时,Chrome 出现错误。 不管 return 语句在没有函数的情况下是不允许的,这里应该发生了提升,我应该得到一个警告说 undefined。当我有一个 return 语句时,我没有看到这种情况发生。【参考方案5】:

这是 JavaScript 提升的东西,简单来说,我们正在尝试打印变量的值,它没有保存任何值

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

var myVar1
alert (myVar1)
return false

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

【讨论】:

以上是关于为啥返回后变量提升在某些浏览器上有效,而在某些浏览器上无效?的主要内容,如果未能解决你的问题,请参考以下文章

为啥浏览器在现有脚本上返回 404?

为啥浏览器可以推断出某些省略的 HTML 元素,但不能推断出形成有效标记所需的所有省略的元素?

为啥在某些语言中使用变量之前需要声明变量,而在其他语言中则不需要? [关闭]

为啥此输入类型=时间在某些带有“stepMismatch”的浏览器中无效:true?

Adobe Flex:为啥在某些浏览器上会出现间歇性 SecurityError 事件?

为啥某些 Flask 会话值在关闭浏览器窗口后会从会话中消失,但稍后会在没有我添加它们的情况下重新出现?