Pull to refresh

Comments 122

typeof null; // object
null === Object; // false
на мой взгляд логично
typeof {};
Object === {};
не то что логично, это правильно, не знаю какой дурак придумалсравнивать тип со значением…
Необычное поведение NaN — требование IEEE 754, общее для всех языков программирования.
Чтобы типу Number можно было присвоить NaN.
Чтобы NaN не был равен ничему другому.
Если NaN ничему не равен, как тогда проверить на NaN?

Должна быть возможность узнать, является ли число NaN, иначе смысле в NaN — нет
Для этого имеется функция isNaN()
Именно поэтому NaN == NaN имеет значение false.
UFO just landed and posted this here
UFO just landed and posted this here
зачем много писать? надо проще смотреть на вещи: return false;
Фишка в том что NaN === NaN; // false
UFO just landed and posted this here
Чтобы не возникало ошибки, когда математическая операция возвращает неизвестно что, например при делении нуля на ноль, интерпретатор по стандарту должен возвращать NaN.
Infinity === 1/0 // true

то ли Infinity === NaN, то ли 1/0 у них *равно* бесконечности.
NaN'у ничего не может быть ни равно ни эквивалентно
UFO just landed and posted this here
деление на 0 в математическом смысле на самом деле бесконечное число
NaN получается в арифметических операциях, которые либо ошибочны (деление на строку), либо второе =) мало ли что могут сделать со знаком "+"
0/0 даёт NaN — это неопределённая операция.
1/0 даёт бесконечность — это общепринято в математике.
более того, в C# разделяют NaN и PositiveInfinity / NegativeInfinity
Вы не поверите:)
В JS есть и Infinity, и Number.NEGATIVE_INFINITY, и Number.POSITIVE_INFINITY.

в JS тоже есть +infinity и -infinity
Вы не поверите, но это не C#, а IEEE 754.
говорю, что знаю, с JS не настолько знаком :) не хотел никого обидеть
сразу видно кто прогуливал занятия х) «бесконечно малое» — это прогрессия. а 0 — это число. бесконечность — условное обозначение предела бесконечно увеличивающейся прогресси (точнее его отсутствия ;-))
UFO just landed and posted this here
Java:

public final class Double

public static boolean isNaN(double v) {
return (v != v);
}

}

всё правильно =)
а нет того же на русском?
Я не гуру js, я его только изучаю, и могу посоветовать замемечательную книгу Дэвида Флэнагана «Javascript Подровное руководство». В ней отлично описан каждый из ваших случаев.
Это не мои случаи. Надеюсь, что в реальной жизни не столкнусь с подобным кодом )
На мой взгляд, это может быть полезно и существенно сократить потраченное на разработку время, а так же колличество кода. А выше обозначенная книженция, очень полезна и как учебник и в качестве стправочника).
NaN === NaN; // false

неизвестно что != неизвестно что
Абсолютно согласен. Возможно просто костыль от разработчиков, по тому что логика в этом безусловно есть.
А вот
alert(111111111111111111111); // alerts 111111111111111110000
Наверняка связано с тем что скрипт считает 111111111111111111111 бинарным числом, пытается перевести в десятичную систему, но срабатывают ограничения integer. Может я и неправ, но это, на мой взгляд, наиболее вероятная причина такого поведения
UFO just landed and posted this here
Скорее не так. Любая операция, кроме IS NULL и IS NOT NULL, с NULL'ом даёт NULL. Таким образом NULL = NULL — это NULL, который затем интерпретируется как false, что и выглядит как будто NULL != NULL.
UFO just landed and posted this here
о! раскрыли глаза на жизнь — благодарю! а пруф линк есть?
en.wikipedia.org/wiki/Null_(SQL)#Three-valued_logic_.283VL.29

Каюсь. Согласно этому всё немного не так. Но предложенная мной методика продолжает работать.
Вышеуказанное число превышает допустимую безопасную длину, и поэтому теряется точность в младших разрядах. (Д. Фленаган, «JS. Подробное руководство», раздел 3.1.1)
в С# приведение типов от большего к меньшему приводит к подобному результату, это нормально =)
Скрипту все равно, 11 или 11111111111111111. И 11 это одиннадцать, а не два. Было бы странно считать число двоичным лишь потому, что в нем нет цифр выше 1.
Поправка: Не «два», а «три», разумеется.
О, моя бага там тоже есть? Круто. Только не мной подписано, но это сейчас поправим.
Дело, кстати, не в бинарности, а в том, что заканчивается точность floating point.
Это похоже на операции сравнения с NULL в sql. Как известно, любая операция над NULL возвращает NULL и любая операция сравнения возвращает «неизвестно» или FALSE если операция сравнения с NULL это вся логическая операция.
То, что и с NaN это так же, абсолютно логично.
«Javascript — это язык, который мы любим несмотря на все его ненавистные особенности».
Взяв во внимание вышенаписанную фразу хочу поинтересоваться — кто-нибудь хоть раз сталкивался с проблемами при кодировании из-за вышеперечисленных странностей? Вряд ли. Те, кто находят эти странности подают их под таким соком, будто после таких багов язык для программирования не пригоден вовсе становится.
Думаю, многие сталкивались с проблемами по крайней мере из-за следующих двух «странностей»:

parseInt('08'); // 0

0.1 + 0.2 === 0.3 // false
в 8-ричной системе не может быть цифры 8.
ну а вторая странность я полагаю связана с особенностями представления вещественных чисел.
Да и вообще проверка чисел с плавающей точкой на равенство — дурной тон.
Где странности? С восьмеричной системой, как уже подметили, или с компьютерным преставлением чисел с плавающей точкой?
видимо, автор сайта wtfjs пришёл в js не из программирования, а из верстки. Думаю, многие верстальщики именно из js узнали, что числа бывают восьмеричными и об особенностях компьютерного представления чисел с плавающей точкой.

Просто эти 2 примера, если о них не знать, способны порождать реальные проблемы при кодировании — в отличие от остальных, в большей степени относящихся именно к js.
UFO just landed and posted this here
UFO just landed and posted this here
0.1 + 0.2 === 0.3 — проблема встречается не только в javascript, связана с представлением чисел с плавающей точкой
второй правильнее так: 0.1 + 0.2 — 0.3 < 0.0001 где 0.0001 — точность сравнения
(0.1 + 0.2).toPrecision(3) == (0.3).toPrecision(3)
дело в том что математические операции с плавающей точкой не точны, без округления их сравнивать безсмысленно:
0.1 + 0.2).toPrecision()
0.30000000000000004
смотрим еще:
[] == false // true
а теперь:
var a = [];

if (a) {
alert(1); // но мы тут, надо проверять свойство lenght
} else {
alert(2); // исходя из первого утверждения, можем решить, что окажемся здесь
}
UFO just landed and posted this here
Я считаю себя гуру Javascript. И мне глубоко наплевать на эти «особенности», потому что ни один вменяемый программер такими конструкциями пользоваться не будет, и вовсе не потому, что JS выдает странный результат. А я очень надеюсь, что подобный код я никогда в жизни не увижу.
а я вот попадался на typeof null когда писал дампер обьект->строка, и считаю что знать такие мелочи полезно, даже если не хочешь на них попадаться, не все ведь профессионалы, можно много чего увидеть
UFO just landed and posted this here
Все примеры достаточно просты, по-моему. Не будучи гуру джаваскрипта, но в свое время с удовольствием прочитав Фланагана, ни разу не ошибся.
Результаты приведенного кода верны (если знать Javascript), кроме typeof null == 'object' (это ошибка в первой реализации JS, которую скопировали реверс-инжереры из MS и потом пошла по всем браузерам).
UFO just landed and posted this here
null вполне существующее значение, в отличии от undefined где значения по сути нет
> в отличии от undefined где значения по сути нет

Значение undefined есть ;) Свойство undefined глобального объекта имеет значение undefined.
какой тогда в нем смысл? разве что для безопасного сравнения с несуществующими переменными, тогда эта запись глобального объекта для виду только… или в чем прикол?
Значение undefined (по словам B.Eich) было введено для обособления инициализирующего значения переменных, либо, когда свойство не может быть найдено в базовом объекте.

Значение же null, в отличие от undefined, по смыслу больше связано с объектами, означает пустую ссылку на объект, возможно, зарезервированное место под объект.

Хотя, на мой взгляд, можно было выбрать что-то одно ;)

Здесь есть одна особенность и связана она с оператором typeof, который часто может сбивать с толку, если не знать, как он работает. В большей мере это относится к значению null: несмотря на то, что тип null-a, по определению, Null, typeof для этого значения выдаёт «object»:
alert(typeof null); // «object»

А дело в том, что оператор typeof возвращает строковое значение, взятое из жёстко закреплённой таблицы, где прописано: «для null — возвращать „object“.

Причины этого в стандарте не разъясняются, однако B. Eich (создатель Javascript) отмечал, что null, в отличии от undefined (который означает неопределённость, „нет значения“), используется в большинстве случаев там, где фигурируют объекты, т.е. является некой сущностью, тесно связанной с объектами (конкретно, означающей нулевую ссылку на объект, „пустышку“, возможно, зарезервировавшую место для будущих целей). Но, в некоторых черновиках (например, в невышедшем ECMAscript4 aka Javascript 2.0), был заведён документ, где данный „феномен“ описан, как обычный баг. Также, данный баг поднимался в одном из баг-треккеров, в котором B. Eich также участвовал; в итоге было решено оставить typeof null, как есть, т.е. „object“, хотя сам стандарт ECMA-262-3 описывает тип null-a, как Null.

javascript.ru/blog/Dmitry-A.-Soshnikov/Tonkosti-ECMA-262-3.-CHast-7.-OOP.#tipy-dannyh
Чтобы знать ответы на эти вопросы, совсем не обязательно быть гуру Javascript. Достаточно прочитать пару подобных статей, которые появляются довольно часто, в том числе и на Хабре, и содержат процентов на 80 одни и те же примеры.
UFO just landed and posted this here
Про null как бы логично, оно не может быть ни false ни true. NaN тоже не может быть идентично другому NaN. Это же не переменная и не константа, это не существующее, не существующее нельзя с чем-то сравнивать.
NaN — вполне существующее =)
Не так давно мне вот такая особенность взломала мозг:

var wtf = somevar = {};
somevar.msg = 'hey, wtf';
alert(wtf.msg); //o_O wtf?

wtf и somevar очевидно ссылки на один и тот же объект
Понимаю, но неожиданно это.
Что в этом неожиданного? Объекты в JS передаются по ссылке, это и новичку должно быть известно.
> Объекты в JS передаются по ссылке

«По разделению» (либо по особому виду «по значению»): javascript.ru/blog/dmitry-a.-soshnikov/tonkosti-ecma-262-3.-chast-8.-strategiya-peredachi-parametrov-funkciu.

Переменные «разделяют» (share) один объект. Но если одной из этих переменных присвоить другое значение, это не значит, что все остальные переменные начнут ссылаться на этот новый объект, как было бы при передаче «по ссылке».
Поразительно. Шестеро человек, которые вас плюсанули — так и не понимают, как работает JS. При это ещё и меня минусанули :D Деградация Хабра.

Ещё раз: объекты в JS не передаются по ссылке, а передаются по особому виду «по значению», либо, так же известному как, «по разделению».
На самом деле я знаю, как это работает, но не могу запомнить, как это называется, поэтому по привычке называю так :) Возможно, другие люди тоже понимают, что «по ссылке» применительно к JS означает «по разделению».
а какая по сути раница? если это преподнести как: присваивание = изменения адреса ссылки, а изменение переменной = изменение объекта по ссылке, по сути получим тот же результат на практите, и более понятное обьяснение для людей не знакомых с JS (помоему такие штуки в других языках называются указатели?)
> а какая по сути раница?

В реализации, в изменении значений. В грамотности. В незаблуждении.

Однако, стоит сказать, что в Ruby, например, называют это (при той же реализации) — по ссылке (вероятно, по той же причине ;)).

> присваивание = изменения адреса ссылки, а изменение переменной = изменение объекта по ссылке

Да, это и есть передача «по значение (адреса)» или «по разделению», но не «по ссылке».

> помоему такие штуки в других языках называются указатели?

Да (с определёнными уточнениями). Для С++ из boost-a больше по смыслу подойдёт shared_ptr.
В Java (не JS, просто хочу показать как в разных стандартах по-разному описывают) то же самое с объектами. В спецификации говорят, что значений-объектов нет, есть только значения-ссылки-на-объекты. И вот эти ссылки уже передаются по значению (как и всё в Java).
Да, в Java (как в ECMAscript, да и как во многих языках) принята терминология «по значению» (если более полно — особый случай по значению, когда значением является адрес).
UFO just landed and posted this here
в любом языке так, объекты всегда передавались по ссылке (пхп4 не в счет)
Ну не скажите… В Си/Си++ всё передаётся по значению.
прикольно и странно :), я думал что классы передаются по ссылке а структуры по значению… но хз, я не очень знаком с С++
UFO just landed and posted this here
UFO just landed and posted this here
если вы когда-нибудь заглядывали в сорцы jQuery, там можно было встретить такое:

jQuery.fn = jQuery.prototype = {...}

и

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

Мда… Учиться не пробовали?
Собственно, в процессе.
Яваскрипт — не мой конек.
UFO just landed and posted this here
typeof null; // object
null === Object; // false
/*
null, хоть и имеет тип "object", не является Object'ом
*/

Тут мне не очень понятно, а что, собственно, ожидалось? Аналогично:

var x = {};
typeof x; // object
x === Object; // false
/*
x, хоть и имеет тип "object", не является Object'ом
*/

Может, вместо === использовать instanceof? Будет веселее (хотя тоже всё логично):

var x = {};
null instanceof Object; // false
x instanceof Object; // true
не обращайте внимание :) люди сравнивают значение с типом и удивляются что оно не совпадает
всё кроме Number.MIN_VALUE достаточно очевидно, хотя и про первое тоже можно догадаться, если вспомнить такие же «трюки» на C/C++
нет никакого трюка — object — тип, а Object — переменная
конечно нет, я говорил только про float point numbers.
и, кстати, js это case sensible язык, по-этому ничего странного в типе object и функции Object не вижу.
«хотя и про первое тоже можно догадаться, если вспомнить такие же «трюки» на C/C++» знач я не так понял
я имел в виду только float point трюки. была как-то забавная задачка для C/C++

int a = 1, b =…, c;
if (b != 0) c = a / b;

при каком значении b программа вываливается?
ответ: при b = MAX_NUMBER

вот тут в js что-то примерно похожее
Сверху уже местами ответили, но я подытожу:

Number.MIN_VALUE > 0; // true
/*
Дело в том, что MIN_VALUE это наименьшее число, БОЛЬШЕ НУЛЯ
JS Doc: Number.MIN_VALUE равняется самому маленькому возможному номеру, который может обрабатывать Javascript. Т.е. 5e-324 (кстати а как оно на 64-х битных машинах?).
*/

typeof null; // object
null === Object; // false
/*
null, хоть и имеет тип «object», не является Object'ом (КО добавляет: Object — это тип, а null — это уже сам объект, пустой. Разница между типом данных и пустой ячейкой типа данных очевидна. Мнимая неочевидность здесь возникает из-за неявного определения объекта. )
*/

NaN === NaN; // false
/*
Впечатляет, да? Я не могу найти этому объяснения. Автор же просто предполагает, что некоторые люди любят иногда понюхать клей...

КО напоминает про существование троичной логики, а так же что NaN — это аббревиатура Not a Number, т.е. не число. Кирпич и Скамейка — не число, но Кирпич не тождественен Скамейке.
*/

typeof NaN; // number
/*
Вот это сильно. Если вдруг кто не помнит, NaN — not a number. (Вот это бы примеру выше дописать!)

JS Doc: Number.NaN — этого достаточно. Но все же дополню, что NaN — это член типа Number.
*/

PS местами не очень грамотно, не не хотел лезть в омут ООП в JS
Object — не тип, это конструктор =) тип именно 'object'
Ну да +) Вы мне простите опечатку?
На 64-битных процессорах оно такое же, ибо double он и в Африке double.
> Мне больше всего нравиться вот этот пример: a[[[[«item»]]]]==a[«item»]; // результат true

Можно сделать, чтобы не было true ;) Хотя, на практике, вряд ли кто-то так будет делать. Здесь всё завязано на методы .toString и .valueOf: измените их в прототипе Array-я, и получите другой результат.
Переопределить можно много моментов, но как всегда возникает вопрос: «зачем?»
> «зачем?»

Никто не предлагает, я ж отметил, что на практике вряд ли кто-то так будет делать. Вопрос в теории и понимании.
Информация к размышленю насчет сравнения массивов:
[] == ![]; // true
[0] == ![]; // true 
[1] == ![]; // false
[] == false; // true
[0] == false; // true 
[1] == false; // false


На самом деле все просто, нужно лишь внимательно почитать спецификацию, к примеру тут есть перевод.
Упс, хабр съел javasсript.ru
Sign up to leave a comment.

Articles