简体   繁体   中英

a variable and function with same name returns an error inside a block

If we declare a variable and a function with same name, it is accepting re-declaration. But when we do the same thing inside a block, it shows re-declaration error .
Code:

 var x; function x() {}; // no error. 

But in this case i'm getting Error.

 { var inside; // re-declaration error. function inside() {}; } 

expected result should be no error.

This is an EcmaScript 6 change. From ES6 onwards it's no longer allowed to have duplicate bindings within a block scope .

The ES5 spec does not have such a restriction but in the ES6 spec the semantics have been changed:

13.2.1 Static Semantics: Early Errors

Block : { StatementList }

  • It is a Syntax Error if the LexicallyDeclaredNames of StatementList contains any duplicate entries.

  • It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList also occurs in the VarDeclaredNames of StatementList .

The first part is relevant - LexicallyDeclaredNames contains all declarations found within the code inside the block.

Presumably, this is part of a change in semantics function declarations in ES6, since now they can be block scoped:

 { //block 1 function foo() { // declared in block 1 return 1; } console.log("block 1: foo() === 1", foo() === 1); { // block 2 function foo() { // declared in block 2 return 2; } console.log("block 2: foo() === 2", foo() === 2); } console.log("block 1: foo() === 1", foo() === 1); } 

This is a syntactic sugar over this equivalent ES5 code:

 (function() { //block 1 var foo = function() { return 1; } console.log("block 1: foo() === 1", foo() === 1); (function() { //block 2 var foo = function() { return 2; } console.log("block 2: foo() === 2", foo() === 2); })(); console.log("block 1: foo() === 1", foo() === 1); })(); 

However, this feature cannot work with duplicate names.

The same behaviour persists for any block, including other types of block statements. Here is an example:

 { //block function foo() { return 1; } console.log("block: foo() === 1", foo() === 1); if (true) { // if block function foo() { return 2; } console.log("if block: foo() === 2", foo() === 2); } for (var i = 0; i < 1; i++) { // for block function foo() { return 3; } console.log("for block: foo() === 3", foo() === 3); } switch ("hello world") { // case block default: function foo() { return 4; } console.log("case block: foo() === 4", foo() === 4); } console.log("block: foo() === 1", foo() === 1); } 

However, it should be noted that duplicate declaration of the same type ( var or function ) do not lead to an error:

 { var foo = 1; var foo = 2; console.log("foo ->", foo); } { function bar() { return "a"; } function bar() { return "b"; } console.log("bar() ->", bar()); } 

So, it seems like they aren't treated as different declarations but overwriting the same lexically declared name.

While exploring this further I came across this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError

The funny thing is that my result is different than theirs for this situation:

    try{
        eval(`{
            var x;
            function x(){};
        }`);
    }catch(e){
        console.log(e instanceof SyntaxError);
        console.log(e.message);                // "Hello"
        console.log(e.name);                   // "SyntaxError"
        console.log(e.fileName);               // "someFile.js"
        console.log(e.lineNumber);             // 10
        console.log(e.columnNumber);           // 0
        console.log(e.stack);                  // "@Scratchpad/2:11:9\n"
    }

Result:

true // instanceof SyntaxError
06:01:10.526 VM3194:22 Identifier 'x' has already been declared // e.message
06:01:10.527 VM3194:23 SyntaxError // e.name
06:01:10.527 VM3194:24 undefined   // e.filename
06:01:10.527 VM3194:25 undefined   // e.lineNumber
06:01:10.527 VM3194:26 undefined   // e.columnNumber
06:01:10.527 VM3194:27 SyntaxError: Identifier 'x' has already been declared at VM3194:16 // e.stack

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM