Почему сравнение целого числа с массивом длины 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:
- Пусть exoticToPrim будет GetMethod (input, @@toPrimitive).
@@toPrimitive
- это символ, к которому вы обращаетесь как Symbol.toPrimitive
. Дело в том, что Array
не имеет этого свойства, поэтому процесс продолжается с этого шага:
- Возврат OrdinaryToPrimitive (ввод, подсказка).
Когда абстрактная операция OrdinaryToPrimitive вызывается с аргументами O и подсказкой, выполняются следующие шаги:
- Если подсказка " строка", тогда а. Пусть methodNames будет " toString", " valueOf" ".
- 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.