Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why JavaScript function declaration behave differently in chrome and safari? [duplicate]

Tags:

javascript

    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.

like image 723
phieo Avatar asked Mar 31 '17 08:03

phieo


People also ask

What makes JavaScript same in all browsers?

Javascript is defined by the ECMA-262 standard, which is updated anually. Every revision has added some new syntax. All browsers since IE5 support a common subset of syntax in the same way, it's only a question of if they support new syntax options or not.

Why is my JavaScript not working on Chrome?

Google ChromeIn the "Settings" section click on the "Show advanced settings..." Under the the "Privacy" click on the "Content settings...". When the dialog window opens, look for the "JavaScript" section and select "Allow all sites to run JavaScript (recommended)". Click on the "OK" button to close it.

Is JavaScript supported by all browsers?

All the modern browsers come with built-in support for JavaScript. Frequently, you may need to enable or disable this support manually. This chapter explains the procedure of enabling and disabling JavaScript support in your browsers: Internet Explorer, Firefox, chrome, and Opera.

How functions are declared in JavaScript?

Function declarationsThe name of the function. A list of parameters to the function, enclosed in parentheses and separated by commas. The JavaScript statements that define the function, enclosed in curly brackets, { /* … */ } .


1 Answers

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.

like image 96
RobG Avatar answered Oct 08 '22 22:10

RobG