Javascript- uncaught syntaxerror: identifier * уже был объявлен

console.log(a) //output:ƒ a(){}
var a = 1;
function a(){};
var a = 10;
console.log(a) //output:10

====================

var a = 1;
if(true){
  function a(){};
  var a = 10;
}
console.log(a) // this code throws Uncaught SyntaxError: Identifier 'a' has already been declared

оба приведенных выше фрагмента кода одинаковы, за исключением блока if. почему последний выдает ошибку, когда это допустимо в javascript для удаления одной и той же переменной дважды в той же области с var, как показано ниже

 function a(){};
 var a = 10; //no error

Также для немного другого сценария после удаления var из `var a = 10 в приведенном выше коде он работает нормально, но результат удивляет

 var a = 1;
 if(true) {
   function a(){};
   a = 10;
 }
 console.log(a) //output:ƒ a(){}

Я удивлен, увидев этот вывод, поскольку я ожидаю 10 .. потому что две переменные, объявленные внутри блока if, относятся к той же переменной, объявленной выше, поскольку javascript var не учитывает область действия блока, но функциональную область ... так почему бы не выводить для вышеупомянутого быть 10? где, как показано в приведенном ниже коде, выводится 10, как я и ожидал, при замене определения функции на выражение функции.

  var a = 1;
  if(true) {
    var a = function(){ console.log() }
    a = 10;
  }
  console.log(a) //output:10

Что ж, объявления функций внутри блоков if были недопустимыми в ES5, поэтому их использование будет иметь Семантика ES6 с более строгими правилами в отношении повторяющихся объявлений.

Bergi 11.04.2018 14:34
24
2
102 387
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

This is surprising as javascript var doesn't respect block scope but functional scope...

Конечно, но вы не использовали var для объявления a в области видимости блока. Вы использовали объявление функции, которое делает уважает области блока (иначе было бы полностью неверный код, как в строгом режиме ES5).

It's permissible in javascript to declare same variable twice in the same scope with var as below

То же самое и здесь. Объявление function в блоке использует семантику объявления ES6 (например, let или const), которая не допускает повторного объявления.

Дело 1

console.log(a) //output:ƒ a(){}
var a = 1;
function a(){};
var a = 10;
console.log(a) //output:10

Будет отображаться как

var a;
a = function(){}; // now a holds the value as a function
console.log(a); // output : f a(){}
a = 1; // a is a var that holds value 1
a = 10; // a is a var that holds value 10
console.log(a); // output : 10

Случай 2

var a = 1;
if(true){
   function a(){};
   var a = 10;
}
console.log(a)

Будет отображаться как

var a;
a = 1;
if(true) {
    a = function() {};
    let a; // The function declaration in the block uses ES6 declaration semantics (like let or const), which does not allow re-declarations.
    var a; // throws Uncaught SyntaxError: Identifier 'a' has already been declared
    a = 10;
}
console.log(a);

Случай 3

var a = 1;
if(true){
    function a(){};
    a = 10;
 }
console.log(a)

Будет отображаться как

var a;
a = 1;
if(true) {
    a = function() {};
    let a;
    a = 10;
}
console.log(a); // output : f a(){}

Случай 4

var a = 1;
if(true){
    var a= function(){console.log()}
    a = 10;
}
console.log(a)

Будет отображаться как

var a;
a = 1;
if(true) {
    a = function(){console.log()}
    a = 10;
}
console.log(a) // output:10

Дело 5

var a = 1;
if(true){
    function a(){};
    a = 10;
    console.log(a) 
}
console.log(a) 

Будет отображаться как

var a;
a = 1;
if(true){
    a = function() {};
    let a;
    a = 10;
    console.log(a); // output:10
}
console.log(a); // output : f a(){}

Больше похоже на let a в корпусе 3.

Bergi 11.04.2018 14:44

@Bergi - Спасибо. Я взял ссылку из вашего ответа при публикации своего понимания. Надеюсь, с тобой все в порядке. Если нет, то с радостью удалю свой автоответчик.

Nikhil Aggarwal 12.04.2018 07:23

@PrashantTapase - Спасибо. Я обновил свой ответ для лучшего понимания, и теперь вы также можете увидеть поведение с ложными утверждениями.

Nikhil Aggarwal 12.04.2018 08:06

@nikhilagw Ничего страшного :-)

Bergi 12.04.2018 10:18

@nikhilagw отлично .. все очень ясно и спасибо за ответ с подробными сценариями ... не могли бы вы также упомянуть, как отображается этот фрагмент кода ... if (true) {function b () {}}? заранее спасибо

venkata 12.04.2018 11:19

Я спрашиваю об этом, потому что, когда я выполняю этот код в chrome console ..console.log (b); // вывод: undefined if (true) {function b () {}} console.log (b); // вывод: ƒ b () {} поэтому я сомневаюсь, что объявления функций обрабатываются как let / const, поскольку b также доступен за пределами блока

venkata 12.04.2018 11:27

@venkata - В вашем случае будет так. var b; console.log(b); if(true) { b = function(){}} console.log(b); Из-за этого первая консоль выдает undefined, а вторая - функцию. Объявления поднимаются в область родительской функции, однако значение устанавливается только в области. Любое определение функции в блоке в основном заканчивается блокировкой имени переменной в этом блоке, как это делают let и const, однако связь функции всегда с областью родительской функции. Надеюсь, это прояснится.

Nikhil Aggarwal 12.04.2018 11:53

Теперь все очень ясно.Спасибо nikhilagw.Спасибо @Bergi

venkata 12.04.2018 12:46

@venkata, nikhilagw: подробные сведения о объявлениях функций области видимости блока в небрежном режиме в браузерах просто странные. Вам следует использовать строгий режим и игнорировать то, что вы только что видели :-)

Bergi 12.04.2018 13:05

@Bergi - Согласен. Имеет смысл. :)

Nikhil Aggarwal 12.04.2018 14:14

Простое решение - использовать IIFE.

(function() {
var sahil = {
  checkThis: function() {
    console.log(this);

    function checkOther() {
      console.log(this);
    }
    checkOther(); // checkThis() function called in "global context", will
                  // return "this" as "window"
  }
};
var moo = sahil.checkThis;
moo(); // moo() function called in "global context", will return "this" as "window" })();

Другие вопросы по теме