为什么JavaScript函数声明在chrome和safari中表现不同? [英] Why JavaScript function declaration behave differently in chrome and safari?

查看:103
本文介绍了为什么JavaScript函数声明在chrome和safari中表现不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

< pre class =snippet-code-js lang-js prettyprint-override> foo(); if(true){function foo(){console.log(1); } else {function foo(){console.log(2)}}



在chrome中它显示Uncaught TypeError,但在Safari中它显示为2.

解决方案

此行为有一些历史记录。在开始时(假设是ECMA-262 ed 3,这是规范的第一个真实版本),块内部不允许使用函数声明(参见 Kangax,函数语句 )。



然而,IE刚刚对待它们作为函数声明并提升它们,而Mozilla浏览器(可能是Netscape Navigator)有条件地将它们作为函数语句进行评估,这是规范的允许扩展。其他一些浏览器引发了一个错误,这可能是他们本应该做的。



这一系列的行为是非常无法忍受的,所以使用ECMA-262 ed 5 aka ES5,函数语句在附录中正式化(在下一版本中更好地解释了它们,ECMAScript 2015 附录B.3.3块级函数声明Web遗留兼容性语义)。这可能是推动记录各种实现方式的一部分,而不是试图严格执行与意图相反的特定行为,而不是规范的字母。



To修复问题,在严格模式下禁止使用函数语句,这也是ECMAScript第5版引入的。



有关其他内容,请参阅 可以在JavaScript语句中出现函数声明吗? ,以获得良好的Q& A从约5时开始。



最重要的是,如果你想有条件地声明一个函数,请使用函数表达式,这样可以避免函数语句的所有问题因为它们始终受到所有实施的影响:

  var someFn; 

if(something){
someFn = function(... params1){/ * statement list 1 * /};

} else {
someFn = function(... params2){/ * statement list 2 * /};
}

关于 comp.lang.javascript:常见问题解答主题 - 什么是函数声明? 从2010年5月开始。主要阅读JuriykangaxZaytsev和Richard Cornford之间的交流,例如



Kangax:


...你的意思是 - 无关紧要 - 是否是
a函数声明(在输入
上下文时创建)或函数声明(与函数
表达式相同,由Function构造函数创建,在代码执行时创建
),即它们都可以被视为
允许的扩展名?


Cornford:


是的,ECMA语法不允许如果它们在那里,那么
必须是扩展名。允许扩展,因此
也不会被认为是错误的(表面上看,即使IE将命名函数
表达式视为'脱离上下文'函数声明,因此
可能产生两个函数对象,非常奇怪的是
它会被认为是一个bug而不是扩展名。从来没有任何理由期望两个不同的ECMAScript
实现具有相同的扩展,因此
没有理由期望相同的非(ECMA)标准语法导致两个不同环境中的
行为相同。 (当然,如果一个环境
声称兼容JavaScript(tm)并且与ECMAScript
兼容,那么它应该再现在
JavaScript(tm)中找到的扩展名。


这几乎解答了这个问题,并指出为什么应该避免使用函数语句。


    foo();

    if (true) {
      function foo() {
        console.log(1);
      }
    } else {
      function foo() {
        console.log(2)
      }
    }

In chrome it shows Uncaught TypeError,but In safari it shows 2.

解决方案

This behaviour has some history. In the beginning (let's say ECMA-262 ed 3, which was the first real version of the spec) function declarations weren't permitted inside blocks (see Kangax, Function statements).

However, IE just treated them as function declarations and "hoisted" them, while Mozilla browsers (maybe Netscape Navigator) conditionally evaluated them as function statements, an allowed extension to the specification. Some other browsers threw an error, which is probably what they should have done.

That range of behaviours was pretty intolerable so with ECMA-262 ed 5 aka ES5, function statements were formalised in an appendix (they were better explained in the next version, ECMAScript 2015 Appendix B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics). This was probably part of the push to document what various implementations do rather than trying to rigidly enforce particular behaviour that was contrary to intent but not the letter of the spec.

To fix things, function statements were prohibited in strict mode, which was also introduced with ECMAScript ed 5.

For additional reading, see May function declarations appear inside statements in JavaScript? for a good Q&A from about the time of Ed 5.

The bottom line is that if you want to conditionally "declare" a function, use function expressions, which avoid all issues with function statements as they are consistently treated by all implementations:

var someFn;

if (something) {
  someFn = function(...params1) {/*statement list 1*/};

} else {
  someFn = function(...params2) {/*statement list 2*/};   
}

There is a discussion on this topic on comp.lang.javascript: FAQ Topic - What is a function statement? from May 2010. Mostly read the exchanges between Juriy "kangax" Zaytsev and Richard Cornford, e.g.

Kangax:

… You mean -- it doesn't matter -- whether it is a function declaration (which is created on entering the context) or a function statement (which the same as function expression and created by the Function constructor is created at code execution), i.e. both of them can be treated as just an allowed extension?

Cornford:

Yes, ECMA syntax doesn't allow for either so if they are there they must be extensions. Extensions are allowed so neither can be considered wrong (on the surface, even if IE's treating named function expressions as 'out of context' function declarations, and so potentially producing two function objects, is so unhelpfully odd that it would be better considered a bug than an extension). There has never been any reason for expecting two different ECMAScript implementations to have the same extensions, so there is no reason for expecting the same non-(ECMA)standard syntax to result in the same behaviour in two different environments. (Of course if an environment claims to be JavaScript(tm) compatible in addition to being ECMAScript compatible then it should be reproducing the extensions found in JavaScript(tm)).

Which pretty much answers the question and notes why function statements should be avoided.

这篇关于为什么JavaScript函数声明在chrome和safari中表现不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆