Отсутствие точки с запятой перед [] вызывает ошибку в 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, Вы можете получить различные ошибки.