Я только что заметил любопытное поведение в 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
, в котором вы должны объявить переменные перед их использованием.
Может кто-нибудь объяснить, почему это действительно так?
@CertainPerformance - есть ли по этому поводу документация? Это просто мысленно выглядит как плохой код. Но это работает
Фактически, a
объявляется как глобальная переменная, когда вы просто присваиваете ей значение. Он будет систематически объявляться как часть глобального объекта window
.
Если вы посмотрите на ссылка MDN var
, вы увидите, что:
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.
Вот почему код, которым вы поделились, работает отлично и не вызывает ошибок.
Что объясняет его. Я никогда не знал, что можно присвоить значение необъявленной переменной d .. Исходя из ООП PHP, это немного сбивает с толку.
@NelsonOwalo Да, JS довольно сильно отличается от других языков ООП с объявлениями переменных, объектами, типами, проптотипом, модулями и многим другим;)
Обычно JS не вызывает ошибки для необъявленных переменных, но им присваиваются значения.
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.
Если вы хотите получать такие ошибки, добавьте свой скрипт в строгом режиме, используя строку "use strict";
в верхней части вашей функции.
"use strict"; Defines that JavaScript code should be executed in "strict mode". With strict mode, you can not, for example, use undeclared variables.
Это предоставленный вами код, который не вызывает ошибки:
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.info(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
}
Я не знал о "use strict", +1, но я думаю, это нужно удалить в javascript, иначе мы все будем иметь глобальные переменные повсюду, не зная об этом.
Нельсон, директива strict должна быть включена в начало функции, а не в файле. Итак, у него нет проблем с глобальной переменной. Обычно мы все используем директиву strict таким образом, чтобы получить от нее преимущество без каких-либо проблем.
Здесь происходит несколько вещей. Постараемся объяснить каждую из них.
Во-первых, в строке ниже у вас есть несколько выражений, разделенных запятой. В 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 - это, по сути, инструкция. Помните, что вы можете писать выражения внутри условия if.
Выражение
a = 'A|B|C'.split('|')
действительно создает переменнуюa
, она просто неявно присваивается глобальному объекту.