Необъявленные переменные в операторе ..if не выдают ошибку - PullRequest
0 голосов
/ 25 октября 2018

Я только что заметил странное поведение в Javascript.В своем стремлении написать короткий код я придумал следующую функцию:

if(a = 'A|B|C'.split('|'), a.length > 1){
  // I have access to a, but it was never declared as a variable?
} else {
  // some code
}

// I still have access to 'a' over here?

Я ожидал, что код выдаст ошибку о том, что a не объявлен, но, очевидно, он присваивает значение 'A|B|C'.split('|') к нему и используя запятую, я могу использовать a в качестве обычной объявленной переменной.

Более того, переменная существует вне оператора if, и у меня есть доступ к ней вкод, который следует ниже.

Другая вещь, явно устанавливающая переменную:

if(let a = 'A|B|C'.split('|'), a.length > 1)

Выдает ошибку.Это отличается от цикла for, for ..in, в котором вы должны объявить переменные перед их использованием.

Может кто-нибудь объяснить, как это допустимо?

Ответы [ 3 ]

0 голосов
/ 25 октября 2018

Обычно JS не выдает ошибку по необъявленным переменным, но им присваиваются значения.

При присвоении значения необъявленной переменной неявно создается ее как глобальная переменная (она становится свойством глобального объекта) при выполнении присваивания.

Если выесли вы хотите получать ошибки такого рода, то добавьте свой скрипт в строгом режиме, используя строку "use strict"; в верхней части вашей функции.

"используйте строгий";Определяет, что код JavaScript должен выполняться в «строгом режиме».В строгом режиме нельзя, например, использовать необъявленные переменные.

Это предоставленный вами код, который не выдает ошибку:

if(a = 'A|B|C'.split('|'), a.length > 1){
  // I have access to a, but it was never declared as a variable?
} else {
  // some code
}
console.log(a);

Это код, в котором я только что добавил строгую директиву вверху, и она начинает выдавать ошибку.

"use strict";

if(a = 'A|B|C'.split('|'), a.length > 1){
  // I have access to a, but it was never declared as a variable?
} else {
  // some code
}
0 голосов
/ 25 октября 2018

Здесь происходит несколько вещей.Постараюсь объяснить каждый из них.

Во-первых, в строке ниже у вас есть несколько выражений, разделенных запятой.В JS каждое выражение оценивается слева направо, и возвращается последнее выражение.Таким образом, в основном это будет работать следующим образом:

if(a = 'A|B|C'.split('|'), a.length > 1){ // evaluate 'A|B|C'.split('|') and assign the value to a variable 'a' if it exists. Otherwise create a new global variable 'a' and assign the value.

преобразуется в

if(a,a.length > 1) // a gets assigned a value which 
// here is an array consisting of 3 elements.["A","B","C"].

преобразуется в

if(["A","B","C"], ["A","B","C"].length > 1)

преобразуется в

if(true) // comma separated expression always 
// returns the last expression's value which here would be true since a.length is 3

Следовательно, вы всегда получите код блока if.

Вторая проблема, о которой вы упомянули, заключается в том, что вы не можете писать операторы внутри блока if.и использование var / let - это в основном утверждение.Помните, что вы можете писать выражения внутри, если условие.

0 голосов
/ 25 октября 2018

На самом деле a объявляется как глобальная переменная, когда вы просто присваиваете ей значение.Он будет систематически объявляться как часть глобального window объекта.

Если вы посмотрите на MDN var ссылка , вы увидите, что:

При присваивании значения необъявленной переменной неявно создается ее как глобальная переменная (она становится свойством глобального объекта) при выполнении присваивания.

Так вот почемукод, которым вы поделились, работает отлично и не выдает никакой ошибки.

...