«Странный» JS
В ДжаваСкрипте полно странностей, да, но популярная картинка, которая получила сейчас широкое хождение (не буду её приводить, просто суть перепишу) имеет отношение только к безграмотности её авторов. Суть такова:
[] + [] // массив + массив
"" // результат — пустая строка
[] + {} // массив + объект
"[object Object]" // В результате получаем объект? Ну ок
{} + [] // объект + массив
0 // 0? Реально?
{} + {} // объект + объект
NaN // Not a Number? WAT?
Выглядит очень всё ооочень странно, если думать, что происходит именно то, что написано в коментариях справа. На самом деле происходящее неверно интерпретировано авторами.
В ДжаваСкрипте фигурные скобки, помимо объекта, задают ещё и блок кода. В данном случае все «объекты» слева — на самом деле блоки кода. Откроем консоль и попробуем это доказать:
Как видите, в левый блок можно без труда добавить код и станет очевидно, что это не описание объекта. Так два последних обсуждаемых примера распадаются на две независимые команды — определение пустого блока кода, который ничего не выполнит и унарную операция «плюс» над пустым объектом или массивом.
С массивом, возвращающим пустоту при суммировании (конкатенации) всё ещё проще — в данном случае производится попытка вызвать метод toString, который у массива выводит строку его значений через запятую. Так как значений нет, строка пустая.
В общем, ничего сильно странного не происходит.
Ну то есть в целом странный синтаксис языка, конечно, без чётких и однозначных правил. Но ничего сильно странного не происходит.
Комментарий для vladon:
Синтаксис языка с чёткими и однозначными правилами, есть принятый стандарт, там всё это описано.
Не надо про стандарт. Это прокол языка, который делали за 10 дней. Я люблю JS, но не стоит писать в духе «так и было задумано».
Комментарий для Иван:
Я нигде не написал, что «так было задумано». Я считаю, что язык надо знать и знаю, что такое поведение стандартизовано — стандарт есть, гадать не надо, надо просто понимать как оно работает. Я это поведение понимаю и никуда не заглядывая, знаю как сделать так, чтобы слева всё-таки было тоже объект.
Да большинство этих WTF-ов от незнания авторами JS и переноса на JS своих знаний других языков или вообще своих фантазий. На wtfjs.com, например первым пунктом вообще идёт какой-то идиотизм. И из всех «wtf-ов» только «The Hungry Variable» не очевиден с самого начала.
Комментарий для Алексей:
Это больше относится к особенностям «вебкитов»
Это очень неочевидное поведение. Оно вынуждает часто заглядывать в стандарт. У ПХП такая же история: вал дикостей, на каждую тебя тыкают в стандарт. Можно утверждать, что ты один умный, а остальные дураки, но сообщество все расставило по местам -- люди массово переходят на Питон\Руби. Хотят понятный код, а не тысячу пунктов в стандарте, чудаки! JS держится, поскольку еще нет альтернатив. Хотя уже пишут JS на Кофе- и Кложуре- скриптах.
Комментарий для Иван:
У ПХП нет стандарта, какой смысл их сравнивать?
Что-то я этого не наблюдаю. Наоборот, появился совершенно необузданный интерес к серверному ДжаваСкрипту. У Пайтона и Руби своя коробка дикостей и на Пайтоне я запросто напишу код, который с первого раза понять будет очень трудно (а Руби не знаю и знать не хочу)
Комментарий для Евгения Степанищева:
Видимо, имелось в виду, что люди массово переходят на Python/Ruby с PHP, а не с JavaScript.
Просим, просим.
Питон, Яваскрипт — так правильнее. И, да, знать всякие вот такие нестандартные штучки в ЯП, очень необычные и wtf’шные, совершенно не обязательно — только если повыделываться, а для реального программирования всё это знать не нужно.
По-моему, чувак на самом деле грамотный, знающий все эти тонкости, но однажды захотевший сделать шоу.
А по теме — такие неочевидные моменты знать стоит, хотя бы чтобы избегать их использования в коде.
Передергиваете. В питоне нельзя сложить список со словарем и получить None, к примеру. Будет либо ошибка, либо потребуется перегружать операторы. Это не превосходство именно питона -- это знак хорошего дизайна языка.
Комментарий для Мимо проходил:
http://bolknote.ru/all/1842/
Комментарий для Артур Мудрик:
Питон — это змея, а Пайтон назван в честь «Монти Пайтона», устал писать каждый раз. А «Яваскрипт» — так я не говорю.
Знать такие вещи — обязательно. Не для того, чтобы их писать, а для того чтобы уверенно разбираться что происходит в коде. Иногда что-то из этой «экзотики» встречается в коде. И вовсе не потому что человек выпендривался, потому что он и не знал, что выпендривается — он код писал.
Комментарий для Иван:
И тут нельзя, вы статью не читали что ли? Вот вам загадка из «Пайтона» (из второго, третий я не знаю): почему object больше пустого массива, но меньше пустого списка?
А как же классика жанра? http://www.youtube.com/watch?v=FqhZZNUyVFM
File «print.py», line 3, in <module>
print(() > object() > [])
Комментарий для angru:
Комментарий для Евгения Степанищева:
При чём тут вебкит? Это просто факт, что range в регулярке работает по коду символа, а не по фантазиям автора.
Оно так и в перле работает
Комментарий для Алексей:
А… не разобрался я.
Без понятия. Это прокол языка -- в тройке исправили. Я трачу свое время эффективней -- не сравниваю объекты разных типов и другим не даю в код-ревью.
Комментарий для Иван:
Ну так и в JS никто не плюсует блок кода с объектом или массивом.
Кстати, я понятие имею. Объект меньше списка, потому что его первая буква «o» (object) идёт до «t» (tuple), а больше массива потому, что буква «l» (list) идёт ещё раньше. То есть сравниваются имена типов.
Все эти вещи нужно знать, не для того, чтобы писать так (я уже писал это выше, напишу ещё раз), а чтобы быстро разобраться в проблеме, когда она возникнет — когда что-то кто-то передаст не туда по ошибке.
[] + {}
Почему получается «[object Object]» а не NaN ?
Получается, что при +{} фигурные скобки воспринимаются как блок кода, а при « » + {} фигурные скобки воспринимаются как объект и вызывается метод toString() ?
Комментарий для Max:
Это не арифметическое сложение, а строковое (конкатенация). У обоих объектов дёргается toString(), потом преобразуется в строку. Можно в этом убедиться, если выполнить:
Комментарий для Max:
Нет. +{} — вызывается унарная операция (второго-то аргумента нет), {} воспринимается как объект. Унарная операция «+» не над числом даёт NaN.
Нет, тут просто не арифметическое сравнение, так как аргументы операции «+» не числа.
Я так понимаю, получается, что если перед {} ничего нет — то это воспринимается как блок кода. Если же перед {} что-то написано, то это уже воспринимается как объект?
{} + {} — первый элемент — это просто блок кода.
({} + {}) — «[object Object][object Object]» т. е. первый элемент воспринимается уже как объект
Я правильно понял?
Правильно. Можно ещё написать так: ({}) + {}. Это надо делать по той же причине, по которой оборачиваются вызов анонимной функции на месте её описания в скобки — чтобы обозначить, что тут выражение. Причём годится любой способ указания, что это выражение, просто скобки — более универсальный.
Не что-то, а то, что указывает на выражение. Например, function a() {} + {}. Тут {} — блок кода, будет NaN, потому что JS разобъёт эту конструкцию на две — определение функции и +{}, а (function a() {}) + {} — тут уже будет выражение и пустой объект. Вернётся конкатенация строковых представлений.
я имел ввиду, что {} после function блок кода, а после плюса — объект.
Комментарий для Евгения Степанищева:
Не обязательно. Практика показывает, что человек, который быстро делает работающее приложение на Angular/Ember/Node.js/Whatewer, пусть даже и с багами (которыми можно заняться потом), гораздо полезнее того, кто заморачивается всякими мелочами. Идеальное знание языка в принципе может понадобиться, когда делаешь библиотеку, предназначенную для разработчиков, и то не всегда.
Комментарий для Roman:
Моя практика говорит о том, что человек в критической ситуации сходу понимающий где проблема гораздо более редкий и ценный, чем те, которые умеют быстро наколхозить. А такие люди (которые быстро понимают где проблема) невозможны без опыта знания тонкостей.
Возможно мы просто разными продуктами занимаемся. У нас продукт большой длительности (годы и десятилетия).
Комментарий для Евгения Степанищева:
Это претенциозные надуманные глупости. Когда, например, вы получаете один результат функции (например, массив) и второй результат функции (например, объект) и видите, что дальше происходит сложение этих результатов, то тут не нужно знать тонкости языка, не нужно быть каким-то сверхопытным сверхначитанным программистом, чтобы прийти к выводу, что происходит бред или магия или слишком тонкие выпендрежные материи и так нельзя и это нужно исправить или переделать или упростить и тогда всё будет хорошо. Еще раз подчеркиваю — совершенно и гиперабсолютно не нужно знать тонкости языка (в частности вот все эти задачки из поста и их вариации).
Вообще, когда вот читаю такие статьи в вашем блоге (про магию языка и что это на самом деле не магия, а нужно просто знать свой язык идеально иначе ты не прогарммист... ну и пошло-поехало), то всегда такое чувство что вы выпендриваетесь и преувеличиваете собсвтенную важность. Выпендрежность заключается в том, что вы пытаетесь блеснуть знаниями и искренне выразить свое фи и удивляться, мол, «как!? это жы элементарщина, это жы азы языка, это жы должен знать любой программист, иначе он не программист, фу, ужас!!1». Такое чувство, что вы специально читаете документацию и лезете в дебри языка, чтобы потом написать в блоге, что это элементарщина, что это вообще прямо очевидно даже слепому не-программисту и позор тем программистам, кто не знает всякие такие необычные штучки в языке. Вы начитались где-то вот о таких необычных тонкостях языка и теперь выпендриваетесь и пытаетесь искусственно искренне удивляться, когда кто-то не знает о том, что знаете (теперь) вы. Программистское ханжество, вот, придумал, это так называется.
Комментарий для Артур Мудрик:
Это мой опыт.
Комментарий для Евгения Степанищева:
Я вообще-то тоже только долгосрочными продуктами занимаюсь. Про вас я в курсе. Ужасный у вас продукт.
Комментарий для Roman:
Про меня вы не в курсе совершенно.
Комментарий для Roman:
Какой из?
Комментарий для Roman:
Абсолютно все. Конечно, я имею в виду компанию, в которой вы работаете. Хотя в вашем Гитхабе я тоже ничего полезного не обнаружил.
Комментарий для Roman:
Ни один работающий в нашей компании сотрудник, не знает подробностей о качестве всех продуктов. Вам-то откуда знать?
Возможно это как-то связано с тем, что программирование — это моё хобби, а не профессиональная деятельность. Видите, вы действительно ничего обо мне не знаете.
Комментарий для Евгения Степанищева:
Я примерно представляю, каким может быть российский продукт, разрабатываемый десятилетиями на ПиЭйчПи, да еще и за гос. бабло. Интересно, много людей туда наколхозило? Хотя, я могу ошибаться, может у вас там «ЕкмаСкрипт Сикс» давно, тогда могу только порадоваться.
Комментарий для Roman:
Теперь всё встало на свои места.
Элементарно ж.
Если питон не может сравнить 2 объекта (у них не обределены методы для сравнения) то он превращает их (одного из них) в строки (берет имя типа) и сравнивает строки через strcmp (object.c:794).
https://docs.python.org/3/whatsnew/3.0.html#ordering-comparisons