Отсутствие точки с запятой перед [] вызывает ошибку в Javascript?
var a = [1,2,3,4];
var b = [10,20,30,40];
console.log([a,b].length)
[a,b].some(function(x){ x.push(x.shift()) });
Я был крайне удивлен сегодня, когда этот код вызвал
[a,b].some(function(x){ x.push(x.shift()) });
^
TypeError: Cannot call method 'some' of undefined
Очевидно, что JavaScript "автоматическая вставка точки с запятой" работает не так, как ожидалось. Но почему?
Я знаю, что вы можете рекомендовать использовать;
везде, чтобы избежать чего-то подобного, но вопрос не в том, лучше ли использовать ;
или нет. Я хотел бы знать, что именно здесь происходит?4 ответа:
Когда я беспокоюсь о вставке точки с запятой, я думаю о том, как будут выглядеть строки, о которых идет речь, без пробела между ними. В вашем случае это будет:
console.log([a,b].length)[a,b].some(function(x){ etc });
Здесь вы говорите движку Javascript вызвать
console.log
с длиной[a,b]
, а затем посмотреть на индекс[a,b]
результата этого вызова.
console.log
возвращает строку, поэтому ваш код попытается найти свойствоb
этой строки, которое не определено, и вызовundefined.some()
неудачи.Интересно отметить, что
str[a,b]
будет разрешаться вstr[b]
, если str является строкой. Как указывает Камиль,a,b
является допустимым выражением Javascript, и результатом этого выражения является простоb
.
В общем случае можно сказать, что неявные точки с запятой могут легко отказать при определении массива в новой строке, поскольку массив, определенный в новой строке, интерпретируется как доступ к свойству значения выражения в предыдущей строке.
Javascript рассматривает новые строки только для обозначения конца оператора, если не окончание оператора после этой новой строки вызовет ошибку синтаксического анализа. Смотрите каковы правила автоматической вставки точки с запятой в JavaScript (ASI)? и ECMAScript 5 spec для точных правил. (Спасибо Rob W и limelights)
Происходит следующее:
Код интерпретируется как
console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });
То есть все как одно утверждение.
Теперь разберем утверждение:
some
вызывается по значениюconsole.log([a,b].length)[a,b]
Значение
console.log([a,b].length)[a,b]
вычисляется путем принятия возвращенного значенияconsole.log([a,b].length)
(undefined
) а затем пытается получить доступ к свойству с именем значенияa,b
.a,b
возвращает значениеb
(Попробуйте сделать это в консоли). Нет никакого свойства со значениемb
изundefined
, поэтому результирующее значение также будетundefined
.Нет метода
some
наundefined
, отсюда и ошибка.
JavaScript не рассматривает каждый разрыв строки как точку с запятой. Он обычно лечит линию прерывается как точка с запятой только в том случае, если он не может разобрать код без точки с запятой. В принципе, JavaScript рассматривает разрыв строки как точку с запятой, если следующий символ, не являющийся пробелом,не может быть интерпретирован как продолжение текущего оператора. JavaScript-окончательное руководство: 6-е изд. раздел 2.4
Таким образом, в вашем случае он интерпретирует линию как что-то вроде
console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });
И это есть причина ошибки. JavaScript пытается выполнить доступ к массиву по результатам
console.log([a,b].length)
. В зависимости от движка JavaScript и возвращаемого значенияconsole.log
, Вы можете получить различные ошибки.