2013-05-21 1 views
7
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()) }); 

Я был очень удивлен, сегодня, когда этот код вызвалНет точки с запятой до [] вызывает ошибку в Javascript?

[a,b].some(function(x){ x.push(x.shift()) }); 
    ^
TypeError: Cannot call method 'some' of undefined 

Очевидно, JavaScript «автоматическая вставка точка с запятой» не работает, как ожидалось здесь. Но почему?

Я знаю, что вы можете рекомендовать использовать ; всюду, чтобы избежать чего-то подобного, но вопрос не в том, лучше ли использовать ; или нет. Я хотел бы знать, что именно здесь происходит?

+2

Посмотрите правила автоматической установки точки с запятой: http://es5.github.io/#x7.9 –

+1

Вот правила - http://stackoverflow.com/questions/2846283/what-are-the-rules -for-javascripts-automatic-semicolon-insertion-asi –

+0

Честно говоря, я думаю, что фактический ответ в приведенных выше ссылках не ниже ответов. –

ответ

10

Когда я беспокоюсь о вводе точки с запятой, я думаю о том, какие линии будут выглядеть без пробелов между ними. В вашем случае, это было бы:

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.

+4

'arr [a, b]' не является многомерным доступом к массиву. Это то же самое, что и 'arr [b]', поскольку 'a, b' - это действительное выражение, которое имеет значение внутреннего выражения после последней запятой. –

+0

Спасибо Kamil! Я обновил свой ответ, чтобы исправить мою ошибку. –

+0

Я не думаю, что console.log возвращает строку. – Marcus

1

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

7

В общем, можно сказать, что неявная полуколока может сбой при определении массива в новой строке, так как массив, определенный в новой строке, интерпретируется как доступ к свойствам значения выражения в предыдущем линия.

Javascript рассматривает только новые строки, чтобы отметить конец инструкции, если не, заканчивая утверждение после того, как эта новая строка вызовет ошибку синтаксического анализа. См. What are the rules for JavaScript's automatic semicolon insertion (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, отсюда ошибка.

5

JavaScript не обрабатывает каждую разрыву строки как точку с запятой. Обычно он обрабатывает строку , перерывы как точки с запятой, только если он не может разобрать код без запятой. В основном, JavaScript рассматривает разрыв строки как точку с запятой, если следующий непространственный символ не может быть интерпретирован как продолжение текущего оператора. JavaScript - The Definitive Guide: 6th Ed. section 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, вы можете получить разные ошибки.