Почему JSON.parse(['1234']) возвращает 1234?

У меня возникают проблемы с пониманием поведения JSON.parse. JSON.parse должен работать только для строк. Но, похоже, это работает для массива, который содержит только одну строку (даже одинарную кавычку), если строка содержит только числа.

JSON.parse(['1234']) // => 1234
JSON.parse(['1234as']) // => throws error
JSON.parse(['123', '123']) // => throws error

Ответ 1

Как вы указали, JSON.parse() ожидает строку, а не массив. Однако, когда задано массив или любое другое нестроковое значение, метод автоматически принуждает его к строке и приступает к немедленному отправке. Из spec:

  • Пусть JText - ToString (текст).
  • ...

Строковое представление массива состоит из его значений, разделенных запятыми. Так

  • String(['1234']) возвращает '1234',
  • String(['1234as']) возвращает '1234as' и
  • String(['123', '123']) возвращает '123,123'.

Обратите внимание, что строковые значения снова не цитируются. Это означает, что ['1234'] и [1234] преобразуются в одну строку, '1234'.

Так что вы действительно делаете:

JSON.parse('1234')
JSON.parse('1234as')
JSON.parse('123,123')

1234as и 123,123 недействительны JSON, и поэтому JSON.parse() бросает в обоих случаях. (Первый не является законным синтаксисом JavaScript для начала, а последний содержит запятый оператор, который не принадлежит.)

1234, с другой стороны, является литералом Number и, следовательно, действительным JSON, представляющим себя. И поэтому JSON.parse('1234') (и по расширению JSON.parse(['1234'])) возвращает числовое значение 1234.

Ответ 2

Если JSON.parse не получает строку, она сначала преобразует вход в строку.

["1234"].toString() // "1234"
["1234as"].toString() // "1324as"
["123","123"].toString() // "123,123"

Из всех этих выходов он знает только, как разбирать "1234".

Ответ 3

Здесь можно отметить две вещи:

1) JSON.parse преобразует аргумент в строку (см. первый шаг алгоритма в спецификации). Результатом ввода является следующее:

['1234']       // String 1234
['1234as']     // String 1234as
['123', '123'] // String 123,123

2) Спецификации в json.org утверждают, что:

[...] Значение может быть строкой в ​​двойных кавычках, или числом, или истинным или false или null, или объект или массив. Эти структуры могут быть вложенный.

Итак, мы имеем:

JSON.parse(['1234'])
// Becomes JSON.parse("1234")
// 1234 could be parsed as a number
// Result is Number 1234 

JSON.parse(['1234as'])
// Becomes JSON.parse("1234as")
// 1234as cannot be parsed as a number/true/false/null
// 1234as cannot be parsed as a string/object/array either
// Throws error (complains about the "a")

JSON.parse(['123', '123'])
// Becomes JSON.parse("123,123")
// 123 could be parsed as a number but then the comma is unexpected
// Throws error (complains about the ",")