Pull to refresh

Comments 68

На мой взгляд, проще прочитать раздел приведения типов (вроде так) в книге JavaScript The Definitive Guide, даже на русском, там подробно расписано про этот момент, а так же про .toString() и другие вещи.
Получилась очередная статья по основам js (причем короткая и не полная), коих предостаточно в сети.
Статья получилась не только неполная, но местами и некорректная. Кроме этого, не сказано главное и основное: оператор строгого равенства "===" не проверяет на «идентичность», такого понятие в языке нет. В действительности этот оператор на самом деле сначала проверяет тип (typeof), а потом проверяет значение. Одного этого достаточно чтобы в любом случае точно предсказать результат.
> Одного этого достаточно чтобы в любом случае точно предсказать результат.

Нет, этого недостаточно:

var a = {}, b = {};
console.log(a === b);
Тут уместна другая аксиома ООП: два объекта никогда не будут равны, даже если равны значения всех свойств объектов.
В ООП нет таких аксиом, поправьте?

В множестве современных языков оператор сравнения для объектов вполне себе перегружается.
метод .equals() или оператор == может и перегружается, а где вы видели перегружающийся оператор ===?
А в каких языках, где есть перегрузка методов, вы видели ===?

Плюс вопрос об аксиомах до сих пор в силе
err, перегрузка операторов
У меня тоже возникло ощущение, что либо после этого:
«Оператор == сравнивает на равенство, а вот === — на идентичность. Плюс оператора === состоит в том, что он не приводит два значения к одному типу. Именно из-за этого он обычно и используется.»
нужно было остановиться, либо же расписывать очень подробно
Полностью с Вами согласен. Вот думаю, после прочтения таких статей, давно уже изъезженных, а самое главное хорошо описанных в спецификации, думаешь, ну неужели в javascript нету куда более тонких мест чем, точно хорошо описано его создателями. Мне куда интереснее было бы почитать, про разное поведение в разных движках языка(не только браузерных). Уж лучше написать статью про определение типов написать, хотя это тоже тема разобрана по кусочкам.
Я в скором времени буду писать про knockout.js и некоторые недокументированные особенности.
> Так что решил полностью раскрыть эту тему
полностью? да ладно.
Например, что вернёт «NaN === NaN», или как кастятся объекты, +0 тоже самое что и -0? и т.д.
Там в принципе тонкости есть свои.
Под конец мувика я громко ржал :)
Когда увидел название статьи, хотел было сказать, что такой узкой темы маловато для статьи, но раскрыто шикарно, спасибо!
abc === undefined;	// true - только если abc = undefined!

Вот так точно делать не стоит. undefined не зарезервированное слово, поэтому нужно проверять как typeof === 'undefined'
(function(undefined) {
  // тут правильный undefined
})();
бесспорно, но об этом нигде не упомянуто
Об этом знают, например, все, кто когда-либо читал исходный код jQuery.
Не только, это очень много где используется.
Зачем, если итак работает?
Дело в том что undefined это не совсем ключевое слово и может быть переопределено. Ничто не мешает одному из скриптом на странице выполнить такой код:
undefined = true
Это да, но это актуально только если пишешь библиотеку/фреймворк или не доверяешь собственному коду.
Кстати есть более краткая форма, которую я, правда, нигде больше не видел:
var undef;
// undef — правильный undefined
Да назовите как угодно, это будет просто имя нигде не определенной переменной.
А вы доверяете своему коду? Зря.
* если не доверяешь собственной голове
А ежели над проектом работает не только ваша голова?
undefined — это свойство global (он же window), у которого Writable == false (менять не можем значение) и Configurable == false (не можем его удалить).
А можно еще так:
abs === void 0
abs === eval()
abs === [].pop()
abs === {}.a

Последние 2 конечно можно подпортить модификацией прототипа Object и Array
Object.prototype.toString.call( var ) === '[object Undefined]'
void 0 используется кстати в CoffeeScript, он подменяет все вхождения undefined этим значением.
Не поверите, но такая конструкция используется даже в jQuery.
Спасибо, я знаю. Я сам такую конструкцию юзал, когда свой jQuery писал.
Мне просто интересно. А вот так стоит делать?:

abc === void 0;

void зарезервированное слово
У вас один знак равенства лишний — typeof всегда возвращает строку.
a == a; // true
a === a; // true
ну это уже совсем.
В целом — статья достаточно пустословная. Просто раскрытое понятие, что делает абсолютное сравнение (а именно — проверка без приведения). Любой, кто изучал js чуть глубже, чем $('.hide').click(function(){$(this).hide())}) (да и не только js, достаточно много языков, где есть такая же конструкция), знает в чем разница. А действительно сложные и спорные моменты не раскрыты
Просто для меня это как-то элементарно было… Но ссылку в статье привёл. И кстати я объяснил, почему new Number(10) === 10 возвращает false. В JS garden этого нету
Не спорю. Ссылку оставил потому, что она полезная, притензий к вам никаких нет :)
Вы еще на главной про объявления переменных расскажите.
abc  == undefined;	// true, если abc = undefined | null | 0 | false | '' | а также [] в IE6

Заблуждение из PHP. Смотрим:
console.log( 0     == undefined ); // false
console.log( false == undefined ); // false
console.log( ''    == undefined ); // false


undefined нестрого равен только null и наоборот.
Да я полностью с Вами согласен, и об этом нам говорит спецификация es5.github.com/#x11.9.3, в которой не так много уж много букв, чтобы не осилить ее( в частности по поводу операторов).
Почитайте, там много интересного. Вот, например, одна из прекрасных пудр для мозгов:

Number.prototype.a = function(){}();
Number.b = 7;

var a = 123,
    b = Infinity,
    c = new Number(b);

c.b = b.b = a.a = true;

console.log(typeof a.a); // ?
console.log(typeof b.b); // ?
console.log(typeof c.a); // ?
console.log(typeof c.b); // ?
UFO just landed and posted this here
Спойлерну пожалуй.
Собственно 'X.Y' резолвится как Reference(base: 'X', refname: 'Y').GetValue().
«Конструктор» тупо заполняет внутренние члены класса Reference, основная логика ложится на GetValue().
Примитивы (Type(123) и Type(Infinity) == Number (не, не класс)) конвертятся в объекты Number.
Но фишка в том, что конвертятся только во время выполнения данного метода, то есть a.a = true проходит вполне нормально. Но после выполнения a становится снова примитивом.
На время второго обращения он снова превращается в объект, но это новый объект, без заполненного свойства. Если бы нас не пытались дурить (Number.b = 7, хаха), а написали правильно через прототип, то вторая строчка была бы number.
Это что касается первых двух выводов в лог.
Для резолва свойства объекта управление переходит на внутренний метод типа Object — Get().
Который зовёт GetPropery() и в нашем случае возвращает два дескриптора — для ".a" и ".b", для второго случая всё понятно — вернётся четко «true», подводных камней нет.
А на первом опять ловушка на невнимательность. Это FE с одновременным вызовом функции, замыкание, да. Ну и всем, надеюсь, известно, что по-дефолту без return'a функция возвращает undefined.
А typeof undefiend == 'undefined'.
PS: как-то так, возможно наврал в именах функций.
Как-то много букв, но на самом деле используется только одна фишка — «забывчивость» on-the-fly объекта, всё остальное — тупо на внимательность.
Спасибо, поправил. Это верно не для undefined, а для false. Заодно немножко дополнил статью.
И опять неправильно написали!
abc  == false;	// true, если abc = undefined | null | false | 0 | '' | а также [] в IE6

var abc = undefined;
console.log(abc == false);// false
Прошу прощения, действительно. С null и массивами тоже поправил
Напишите про конкатенацию, пожалуйста. Не разберу в чём различие += и -=.
var a = 5;
a += 2; // теперь a = 7
a -= 5; // теперь a = 2

a + 2; // возвращает 4 (2 + 2), при этом a = 2
a - 1; // возвращает 1 (2 - 1), при этом a = 2 до сих пор

Здесь должна быть табличка с надписью «сарказм».
Вашу функцию:

function isEq(a, b){
if(a == b) return true;
for(var i in a){
if(!isEq(a[i], b[i])) return false;
}
for(var i in b){
if(!isEq(a[i], b[i])) return false;
}
return true;
}

Можно переписать гораздо короче:

function isEq(){return true}

Результат будет тот же :)
захотелось расширить, а просто 5 не расширяется


5..property = "value";
Другой разговор, что прочитать это потом нельзя! расширить можно.
var a = 5;
a.abc = 10;
a.abc; // undefined

a = new Number(5);
a.abc = 10;
a.abc; // 10


То же самое с String и Boolean.
Мои пять копеек
new Number(5).valueOf() === 5; // true
Да, любое число — это объект класса Number.

Нет, на самом деле в JS есть простые типы. Число 5 — это простой тип, а вот new Number(5) — это объект класса Number. Поэтому они и не равны при строгом сравнении.
Плюс:
typeof 5; // number
typeof new Number; // object
Что касается «передачи в this» — там происходит автоматический боксинг примитивных типов, соответственно this будет содержать соответствующий объект (аля new Number(5)).

Но тут тоже есть ньюанс — в strict mode this может быть примитивным типом (автоматического боксинга там не будет):

(function() { console.log(this === 5); }).call(5) // false
(function() { "use strict"; console.log(this === 5); }).call(5) // true
Sign up to leave a comment.

Articles

Change theme settings