Почему сравнение целого числа с массивом длины 1 возвращает true, а false - с массивом длиной 2 или более?

Почему сравнение 0 с массивом длины 1 возвращает true, тогда как возвращает false для длины массива 2 или более? Например,

var a=[]  //undefined
0<a  //returns false
a.push(1) // [1]
0<a // returns true
a.push(2) // [1, 2]
0<a // return false
a.push(3) // [1, 2, 3]
0<a // return false

Ответ 1

В основном вы получаете преобразование типа implicid, сначала toString,

Объект Array переопределяет метод toString Object. Для объектов Array метод toString соединяет массив и возвращает одну строку, содержащую каждый элемент массива, разделенный запятыми.

JavaScript вызывает метод toString автоматически, когда массив должен быть представлен как текстовое значение или когда массив ссылается на конкатенацию строк.

как join работает, а затем преобразуется в число.

what you do   what you get  result  array        string      number
------------  ------------  ------  ---------    --------    ----------
var a = [];
0 < a         0 < 0         false   []        -> ''       -> 0
a.push(1);
0 < a         0 < 1         true    [1]       -> '1'      -> 1
a.push(2);
0 < a         0 < NaN       false   [1, 2]    -> '1,2'    -> NaN
a.push(3);
0 < a         0 < NaN       false   [1, 2, 3] -> '1,2,3'  -> NaN

Ответ 2

Сравнение числа и массива вызовет преобразование типа. Спецификация EcmaScript устанавливает правила для этого в разделе раздел 7.1.3. В соответствии с этими правилами число не преобразуется в другой тип данных, но объект (массив является объектом) будет подвергаться преобразованию, которое выглядит следующим образом:

  • Пусть primValue является ToPrimitive (аргумент, номер подсказки).
  • Возврат ToNumber (primValue).

Функция ToPrimitive описана в раздел 7.1.1:

  1. Пусть exoticToPrim будет GetMethod (input, @@toPrimitive).

@@toPrimitive - это символ, к которому вы обращаетесь как Symbol.toPrimitive. Дело в том, что Array не имеет этого свойства, поэтому процесс продолжается с этого шага:

  1. Возврат OrdinaryToPrimitive (ввод, подсказка).

Когда абстрактная операция OrdinaryToPrimitive вызывается с аргументами O и подсказкой, выполняются следующие шаги:

  1. Если подсказка " строка", тогда   а. Пусть methodNames будет " toString", " valueOf" ".
  2. Else,
      а. Пусть methodNames будут " valueOf", " toString" ".

Как подсказка " число", мы находимся во втором случае. Следующие шаги объясняют, что эти методы применяются по порядку.

Теперь Array.prototype.valueOf просто возвращает сам массив, поэтому следующий подшаг не будет возвращен, так как Type является Object (а именно Array).

5.c.iii Если Тип (результат) не Объект, верните результат.

Как следствие, резервный удар в и toString вызывается в массиве.

Итак, массив преобразуется в строку. Это результат первого из двух шагов, перечисленных вверху:

  • Пусть primValue является ToPrimitive (аргумент, номер подсказки).
  • Возврат ToNumber (primValue).

Второй шаг проще: строка затем преобразуется в число, которое описано в разделе раздел 7.1.3.1.

Поскольку метод Array.prototype.toString создает список, разделенный запятыми, эти строки становятся определенно недопустимыми числами, как только массив имеет более одного элемента. Как уже упоминалось в спецификациях, возвращаемое значение равно NaN.

Любое сравнение < с NaN возвращает false, что объясняет полученный результат.

Ответ 3

если вы проверите массив как число после каждой из строк выше, вы получите ответ, который вам нужен. Помните, что javascript выполняет некоторые приемы при сравнении

Number(a); //insert this after each line

Ответ 4

На слабо типизированном языке, таком как JS, вы должны обратить внимание на то, как изменяемый тип, подобный массиву, принуждает к неизменяемому типу. В основном [1,2] становится "1,2".

So [1,2] == "1,2" // <- true

Ответ 5

Если вы хотите сравнить lenght массива, используйте a.length.

Ответ 6

В JS, если в вашем массиве есть только 1 элемент, js будет считать его значение подобно элементу, в вашем случае - число. например:

var b[]
b.push(8);
b == 8 //true (but b === 8 is false!)

И если у вас в массиве больше 1 элемента, тип массива - массив [число], и это отличается от числа, и из-за этого вы не можете сравнить его с числом.

Вот почему у вас код после вас:

var a=[]  
0<a  
a.push(1) 
0<a 

Вы становитесь истинным, потому что значение теперь "1" и оно больше 0. Но после следующего нажатия значение равно [1,2], а не число (NaN), и именно поэтому вы становитесь ложным.

Ответ 7

Для сравнения javascript пытается конвертировать операнды в число обычно (предпочтительно).

Посмотрите на этот пример:

console.log("test" == true);//false
console.log("test" == false);//false

Почему? потому что "тест" пытается преобразовать в Number, поэтому Number ( "test" ) дает NaN и NaN не равно ни истинному, ни ложному. Аналогично,

0<a becomes 0 < Number(a) becomes 0 < 0 returns "false".

В качестве специального случая, когда массив имеет один элемент, Number способен принуждать его к числу, но когда вы добавляете несколько элементов, какое число должно быть возвращено? В этом случае Number (arr) становится NaN и снова 0 не меньше NaN.