First look at a piece of code:
1.F = function () {return true;}; 2.G = function () {return false;}; 3. (function () {4. if (g () && [] = =![]) {5. F = function f () {return false;}; 6. function g () {return true;} 7. } 8.}) (); 9.console.log (f ());
Understanding the above code has several key points:
- 4th Line of code understanding, if conditions [] = =! [], including the Falsy value, the = = Operator's logic
- About function declarations, if condition in g ()
Say the answer first, in fact, this code returns false under Chrome and returns True under Firefox. Why are there different outcomes? Let's see and analyze.
First of all, to see [] = =! [] This very strange comparison of the value, here is to take an empty array to the inverse value of the empty array compared to the first look must be false ah. However, its value is true. First we look to the right! [], an empty array is reversed, then it means to convert an empty array to a Boolean value, and then inverse, in JavaScript, all objects are used as a Boolean value is true, an empty array is an object, so an empty array is also true, Then take the inverse of the empty array, which is equivalent to!true, so! The value of [] is false.
OK, since the right is finished is false, now we are equal to look at [] = = False, just said the empty array is the object is true, it is obvious that this comparison is true = = False, is to return false right? But no, this comparison will return true, is it a bit crazy? Calm down. According to ECMAScript's specification of = =, such an expression is ultimately done
- Turn false on the right to the value 0
- Turn the left object into a string, and an empty array to a string is an empty string
- Turns the empty string into a number, the result is 0.
- Compare 0 = = 0, return True
The key here is the 2nd step, the array will first turn into an empty string, the null character is actually a falsy value.
As for why Chrome does not behave like Firefox, the 6th line of code function g is declared inside the block.
ECMAScript 5, the current official specification of the JavaScript language, does no define the behavior for function Dec Larations inside blocks.
Functiondeclarations is only allowed to appear on program or Functionbody. Syntactically, they can not be appear in Block ({...})-such as that, if, and for statements. This was because Blocks can only contain statements, not sourceelements, which functiondeclaration is. If we look at production rules carefully, we can see the ' only ' to Expression is allowed directly within Block was when It is part of Expressionstatement. However, Expressionstatement is explicitly defined to don't begin with "function" keyword, and this is exactly why Functiond Eclaration cannot appear directly within a Statement or block (note that the block is merely a list of statements).
But according to ECMA6, quoting the ECMAScript 6 draft-b.3.3 block-level Function Declarations Web Legacy compatibility semantics:
Prior to the sixth Edition, the ECMAScript specification does not define the occurrence of a functiondeclaration as an element of a Block statement ' s statementlist. However, support for that form of functiondeclaration is an allowable extension and most browser-hosted ECMAScript Implem Entations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. [...]
As ES5 does not define the behavior for function declarations inside blocks while allowing proprietary extensions, there a Re technically no "rights" or "wrongs". Consider them "unspecified behavior" which is not portable across different es5-compliant environments.
So, in summary, do not put the declaration of the function inside the block. Remember!!!