Вы до сих пор не любите JavaScript?

С началом эпохи HTML5, рынку понадобилось большое количество JavaScript программистов. Многие специалисты по другим языкам, начали массово переориентироваться на JavaScript. Я много раз видел, как программисты с большим опытом ругали этот, один из самых гибких и могучих, язык, не понимая его принципов. В этой статье я постараюсь рассказать суть и философию JavaScript. Здесь будет всего 4 строчки кода и много-много того, что не напишут в учебниках. Обещаю, что вы полюбите этот язык, или по крайней мере, станете эффективнее в нём. Итак, поехали!

Я по очереди буду рассматривать основные особенности языка и следствия из них. Например, JavaScript обладает очень низким порогом входа. Если вы знакомы с C++ или Java, то можете начать вполне сносно программировать на нём уже через 15 минут после знакомства. Однако, для того, чтобы делать профессиональные вещи, нужно читать документацию, книги по паттернам JavaScript, общаться с более опытными коллегами. Большинство «пузатых и маститых джедаев программирования», конечно же, этого не делают и ругают себя язык. Может, было бы лучше, если бы порог входа был выше? Думаю, что нет (хотя критики было бы меньше). Согласитесь, гораздо проще постигать нюансы, когда вы уже можете написать работоспособный код.

JavaScript мультипарадигменный язык. Он объединяет объектно-ориентированный и функциональный подходы. Так-же доступно структурное программирование и многое другое. Это обусловлено высочайшей гибкостью языка. Функции являются объектами первого рода, переменные могут менять тип, объекты — получать новые свойства на лету. Хорошо это или плохо? С одной стороны, это создаёт проблемы с пониманием у программистов, привыкших к определённости таких языков, как Java или C#. Но это малая плата за эффективность. JavaScript, в большинстве случаев, позволяет создавать приложения гораздо быстрее, чем его строго типизирование товарищи. Приведу всего один пример: я работал в компании, разрабатывающей биржевой терминал. Необходимо было создать настольное приложение на .Net C# и его точную копию в веб на JavaScript. С# приложение разрабатывала команда из 12 программистов в течении двух лет, JavaScript — команда из 3 программистов в течение года. Можно говорить о разнице в квалификации, о том, что возможно влияли другие факторы, но так или иначе разница в 8 раз показательна.

Как же удалось добиться такой скорости разработки? Большинство языков ставят ограничения, якобы для нашего же блага. JavaScript не признаёт ограничений, вы можете менять код где угодно и когда угодно, в том числе гибко патчить чужой код. Если сравнивать языки программирования с политическими системами, то, скажем VBA — это тоталитаризм, вы поставлены в жёсткие рамки и даже не можете посмотреть все исходники. C++ — это демократия, ваша свобода махать руками заканчивается там, где начинается нос вашего собеседника. Это хороший, сильный язык программирования, ограничивающий свободу личности ради общего блага. JavaScript — это анархия, вы можете менять всё что угодно и никто вам не помешает, не ограничит вашу свободу. Проблема в том, что не все могут жить при полной свободе. Нужна высокая внутренняя культура, чтобы не украсть у соседа трактор, даже если тебе за это ничего не будет. То же самое и в коде, например, распространённая практика в JavaScript, не делать приватные свойства истинно приватными. Создаются обычные (публичные) свойства и к их имени просто дописывается знак подчёркивания. Считается, что другие программисты увидят это и не будут использовать это свойство без особой необходимости. Бывают ситуации, когда заложиться на значения приватного свойства или даже модифицировать его, является самым прямым и правильными путём. Да, везде бывают исключения, и JavaScript позволяет нам их делать. В таких случаях, программист разбирается в чужом коде и берёт на себя ответственность за последствия. «Он же может всё сломать!?» — негодуют адепты других языков. Об этом следующий пункт.

В JavaScript нет защиты от дурака. Мы считаем, что все, кто работают над кодом — профессионалы и доверяем им. (пауза) В хорошей JavaScript команде все программисты одного уровня. Он может быть низким или высоким, но не должен слишком сильно отличаться. Так же, как в стране, где все воруют, честному человеку приходится сложно, или в обществе порядочных людей, негодяй сразу получает по заслугам, так же и в анархическом и бесконтрольном JavaScript джуниоры будут ломать код джедаев, а джедаи будут использовать абсолютно не понятные для джуниоров (но понятные для любого профессионала) архитектурные ходы, невольно снижая их продуктивность. Так нужно ли перестраховываться через язык, или лучше просто набирать правильных людей? Некоторые ругают JavaScript за то, что они называют «баги» и «нелогичность». Например:

'3' - 2 === 1;
'3' + 2 === '32';


Это как раз то, для чего после быстрого старта желательно всё-таки прочитать про преобразование типов. Для любого, даже начинающего программиста на JavaScript, приведённые выше примеры тривиальны и абсолютно предсказуемы. За 10 лет подобные вещи ни разу не вызывали у меня проблем. Ещё одна интересная задачка, что вернёт этот код:

Math.max(2, []);
Math.max(2, {});


забавно, но первая строчка вернёт 2, а вторая NaN (Not a Number). Считать ли это ошибкой и нелогичностью? Смотри выше, защиты от дурака в JavaScript нет, и если вы передаёте вместо числа объект или массив — можете пенять только на себя. Точно так же в C++ можно писать в память разный мусор и ругать язык. Если у тебя есть пистолет, то это не значит, что нужно стрелять себе в ногу.

Немного про обработку ошибок — она в JavaScript молчаливая. Это значит, что если программа может продолжаться — она с большой вероятностью продолжится. Скажем, вы поделили на нуль, большинство языков выбросит ошибку и завершит работу, а JavaScript покажет Infinity и, возможно, даже выведет его в интерфейс пользователю в виде строки, если так задумана логика программы. Хорошо это или плохо? Я бы сказал, это позволяет создавать программы с высочайшим уровнем стабильности. Выход из строя одного элемента не выводит из строя всю систему. Конечно, плохо показывать пользователю NaN или undefined, но это гораздо лучше, чем аварийно завершиться, как все мы много раз видели у многих нативных прогамм под Windows (и не только). Мы доверяем программистам и считаем их профессионалами, поэтому в идеальном мире такие ситуации не должны появляться. Если же проблема всё-таки возникла — у нас есть страховка, некоторый запас прочности языка. И, конечно же, в особо важных местах программы мы можем вручную проверять значения на NaN, null, undefined, создавая абсолютно строгий код.

На десерт расскажу видение самой неоднозначной особенности JavaScript — прототипного наследования. Если говорить об Объектно Ориентированном Программировании, то вообще говоря, оно не требует, чтобы объекты обязательно были объявлены через классы. Более того, часто нам нужен какой-то объект в единственном экземпляре, либо нужно создать несколько однотипных объектов, но отличающихся какими-то нюансами — дополнительные поля, флаги, методы и т.п… Часто, классы создавать совсем не обязательно, это излишний уровень абстракции, и прототипное наследование, или даже создание объектов на лету, прекрасно справляется с такими задачами. Согласно принципу бритвы Оккама, не стоит плодить лишний код, если задачу можно решить проще. Такой подход требует не только меньше текста, но и меньше оперативной памяти и процессорного времени. Классы не поставляются из коробки, но если вы пишете большое enterprise-приложение — написать 20 строчек своей реализации классов для вас не составит труда. Если нет — воспользуйтесь одной из многочисленных библиотек, в таких языках как C++ без библиотек придётся гораздо сложнее. Хотя некоторые предпочитают писать на чистом JavaScript, это не так сложно и имеет дополнительные преимущества.

Можно сказать, что JavaScript обладает идеальным, для нашего времени, уровнем абстракции. Вам не нужно думать о распределении памяти, о пятнадцати алгоритмах сортировки, о типе операционной системы. Можно сконцентрироваться на более крупных вещах, таких как архитектура или логика приложения. Можно сказать, что JavaScript это язык именно для программистов, а не для хардварщиков или системных администраторов. Отсекая несущественное, можно добиться по настоящему высокой производительности и создавать качественный и элегантный софт, в поразительно короткие сроки. Разумеется, если чувствовать себя в языке абсолютно свободно.

Последняя и самая важная вещь, которую нужно понимать о JavaScript, связана с его динамической типизацией. Это может показаться странным, но я хочу задать такой вопрос: а для чего вообще существует система типов? В мире людей преобладает не типизованная информация: мы не можем часто провести грань, повесть это или роман, младенец трансформируется в ребёнка, потом в подростка. Можно ли назначить этим стадиям тип и нужно ли это делать? Типы данных естественны для компилятора, гораздо проще преобразовывать код если мы сразу знаем какие примитивы нам подают. Но прогресс движется вперёд и я считаю, что языки с гибкой типизацией — существенным шагов вперёд. В традициях JavaScript, если вам не хватает типов классов — вы можете создать их вручную, написать обёртку, ввести ограничения. Я работал в игровой компании, продукт которой имел очень сложную логику, и они сделали обёртку для классов с жёсткой типизацией, множественным наследованием и блек джеком. JavaScript обладает потрясающим уровнем интроспекции и вы можете подстраивать его под себя в очень широких пределах.

Чтобы быть совсем честным, скажу так же о пожалуй самом существенном минусе JavaScript: профессиональное программирование на нём во многих аспектах сложнее, чем на Java или C#. Если в строго типизированных языках вы видите хотя бы типы аргументов, которые вы принимаете в функцию, то в JavaScript нужно все эти данные держать в голове. Порой вы не можете быть уверены даже в том, какие методы имеет тот или иной объект. Это требует высокого уровня концентрации и хорошего понимания архитектуры. Если вы готовы на это и готовы честно изучить язык, а не слепо кодить с места в карьер — вы получите поистине один из самых мощных инструментов, для создания гибкого и кроссплатформенного программного обеспечения с высокой скоростью.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 241
  • +38
    С# приложение разрабатывала команда из 12 программистов в течении двух лет, JavaScript — команда из 3 программистов в течение года

    Странно, мы например пытаемся перенести максимум логики на сервер приложений (.net / c#) и минимум делать в браузере (js).
    Т.к. был прямо противоположный опыт.
    (C# отлавливает ошибки на этапе компиляции, есть продвинутые анализаторы кода, проще с тестированием/покрытием и т.д.)
    Покрытие кода тестами для js так и не нашли адекватного.
    • 0
      В том проекте логика тоже была на сервере и писалась на Java, но пользовательский интерфейс был довольно сложным, поэтому на клиенте тоже было чем заняться.
      Для тестирования JavaScript могу посоветовать jsTestDriver, Selenium, Mocha или Jasmine, в зависимости от задач. Первый, например, имеет хорошую интеграцию с WebStorm и браузерами, позволяет запусткать юнит-тесты для компонентов интерфейса в один клик. Selenium позволяет писать поведенческие тесты практически любой сложности.
      • +8
        Да, мы знаем про многие способы тестирования, у нас настроен CI в TeamCity для регулярного прогона Selenium тестов, но вот получить покрытие кода, которое тестируется этими Selenium тестами — пока не получилось.
        • +20
          А что писалось раньше, код на C# или Javascript?
          Запросто может быть так, что команда C# сталкивалась с тем, что требований толком нет, или они по сто раз меняются, а потом когда все устаканилось и было ясно что нужно, а что можно выкинуть, пришли все такие в белом на коне Javascript разработчики и сделали в 8 раз быстрее, уже имея точное задание и готовый вариант реализации на другом языке?
        • +1
          В javascript можно не только писать unit-тесты (для которых существует куча библиотек), но и покрыть буквально каждую операцию так называемым code coverage (одна из самых популярных библиотек для этого istanbul).
          Для отлавливания ошибок на этапе компиляции (для js это этап сборки проекта) используются статические анализаторы кода (типа JSLint, eslint и других) или препроцессоры типа TypeScript (в котором есть типизация).

          Но конечно, нужно рассматривать конкретный проект, может быть в вашем случае вы и поступили правильнее перенеся логику на C#.
          • +10
            Как обычно разговор о плюсах javascript плавно перетёк в тему «как бы так спрятать сам javascript, что бы его было не сильно видно программисту».

            Ну вот вы говорите, замечательный язык JS, давайте писать на TS. Мы убили потенциальные плюсы нетипизированости, пишем на сильно кастрированом недо-С# да еще иногда ловим ошибки, связаные с особенностями генерации.

            Стоп, а где, собсвенно, тут JS? Снова затолкали подальше.

            В очередной раз оставлю это здесь:
            github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS
            • 0
              В TS замечательно то, что никто тебя не принуждает использовать типы. В принципе, мне они нужны только для перегрузки функций и более внятного описания классов.
              Но сам я сейчас пишу на ES6 (вот пример) и не могу нарадоваться, хотя типов данных и enum(особенно) и не хватает.
              • +4
                Просто речь о 2 разных языках JS:
                1. Исполняемый язык для браузеров (и др. клиентов).
                2. Язык разработки (описание алгоритма программистами).

                JS отлично выполняет первую роль — кроссплатформенный, достаточно быстрый для множества задач, открытый стандарт. Конечно на его месте мог быть любой язык, но исторически выжил именно он и пока он справляется. Не будем забывать, что в основном — это скриптовый язык. Т.е. язык, который и должен быть максимально гибким в пределах своих разрешений (которые задаются платформой).
                Таким же языком является ассемблер для процессоров.
                Однако, как с повышением сложности задач — всегда требуется новый уровень абстракции, автоматизирующий часть задач (проверка типов, защита памяти, классы). Над ассемблером появился C и др., над JavaScript — Coffee и др. Даже над C# есть множество уровней — это визуальное редактирование форм, связей, свойств и т.д.
                • +1
                  Нет никаких «двух языков», это именно язык разработки. Впрочем, если вы — не разработчик а броузер, то готов принести вам свои извинения. :))

                  А с т.з. разработчика ситуация именно такова, как я описал выше: язык замечательный, но лучше держаться от него подальше.

                  >>Т.е. язык, который и должен быть максимально гибким в пределах своих разрешений (которые задаются платформой).

                  Ух красиво загнули, прямо как на конференции маркетологов…

                  >>Таким же языком является ассемблер для процессоров.

                  Так на ассемблере почти никто не пишет кроме полутора мамонтов. И уж точно я не вспомню статей «ассемблер — это суперязык будущего», «как, вы не любите asm?». Что-то всё больше наоборот.
                  • +1
                    Так на ассемблере почти никто не пишет кроме полутора мамонтов. И уж точно я не вспомню статей «ассемблер — это суперязык будущего», «как, вы не любите asm?». Что-то всё больше наоборот.


                    Люди, у которых хватает образования (и/или навыков) пользоваться asm'ом, уже не будут писать такие желтые и холиварные заголовки. Они просто работают. Так что не показатель.

                    А то периодически видишь на хабре то Excel на JS (о 30-ти строках), то итерацию по live-коллекции в JS кто-то осилил и накатал об этом статью. Смешно ведь.
                    • +1
                      Показатель. Я не знаю, застали ли вы холивары asm VS C/C++, но поверьте, они были и были страшными. Но там хоть аргумент был «в пиковых случаях компилятор не соптимизирует так, как человет»(оказалось — соптимизирует, но это совсем другая история).

                      Но уж точно никому не пришло бы в голову говорить «пишите на asm, он хоть и страшный, как третья мировая, но зато он для процессоров».

                      >>Смешно ведь.

                      Это да.
                    • 0
                      Человек выше пишет о том же самом что и вы, только другими словами. JS — аналог ассемблера, только для браузера. А для разработки он не пригоден, так же само как и ассемблер не пригоден. Только вот на ассемблере *сейчас* никто не пишет, потому что есть инструменты получше, а раньше писали. Сейчас, в 2017 (извините за некропостинг) уже есть неплохие языки, которые транслируются в JS.
              • +1
                Перенесённая на сервер логика ведь тоже может быть написана на js. Одно из преимуществ языка — его распространённость и универсальность — ведь сейчас для написания веб-преложений (сервер + клиент) достаточно знать только js. Считаю это плюсом.
                • +1
                  Мне кажется что тут больше влияет разница между динамической и статической типизацией. То что по английски называют «hacking», позволяет получить продукт гораздо быстрее. Ну и квалификация программистов играет огромную роль, опытные .net разработчики, не измученные поддержкой динозавров, будут работать быстрее и т д.
                  • +7
                    Я вот тоже не понимаю какое это должно быть приложение, чтобы на winforms с каким-нибудь devexpress было бы медленнее нашлепать формочек, чем сделать то же на вебе. Там ведь куча проблем — кросс-браузероность и вообще приколы DOM-а, недостаточно API, недостаточно средств что-нибудь нарисовать/разместить, как следствие — отсутствуют UI библиотеки хоть как-то сопоставимые с winforms.

                    Там где на десктопе надо шлепнуть грид на форму и потыкать его настройки, на вебе — уже задача, причем если повключать в десктопном гриде фичей — часто вообще неподъемная или даже физически нереализуемая.

                    Это все безотносительно совершенно JS и C# — я вот тоже думаю что JS как бы не лучше для UI чем C#. Дело именно в веб vs десктоп.
                    • +1
                      А сколько у вас опыта работы фронт-энд разработчиком? Просто все вот эти домыслы, вроде «физически нереализуемая» — подразумевают отсутствие опыта вообще.

                      Поверьте на слово, в плане UI — html\css\js даст фору любому. Если знать что делать =)
                      • +3
                        Лет 5 из 8 в профессии занимаюсь в основном веб-фронтэндом.

                        Например, делал грид. Надо было там сделать «фиксированные/frozen» колонки — которые не скроллятся, когда остальные — скроллятся. Эта фича, замечу, из коробки в любом декстопном гриде имеется. В вебе — это большая проблема. Можно сходить сюда: trirand.com/blog/jqgrid/jqgrid.html, выбрать демку «Frozen col...\ Frozen Column», вписать дебаггером в фиксированную первую колонку две строчки текста, и посмотреть как оно разъедется. Это можно победить, и я даже знаю как, но в вебе вот такие проблемы — от входа.

                        Я вижу какого объема, в какие сроки и с каким качеством делают приложения люди примерно одного уровня на вебе и на десктопе. Веб в разы менее продуктивен для большинства типов приложений: всякие бекенды с табличками и формами, редакторы текстов и картинок, игрушки, IDE, CAD-ы, и т.п., и т.д. — все это в разы проще делается на десктопе. У веба есть ниша, в которой он хорош — собственно различные сайты, с несложными формочками. Все остальное на нем делается с гемором и требует редкие и дорогие кадры.

                        Это не говорит о том, что плох JS. Плохи html/css/dom, точнее они плохи как основа для более-менее сложных UI.
                        • –3
                          overflow: auto для скроллящихся, overflow: hidden для не скроллящихся. Вот и всё в основном =)
                          • +4
                            Ага, пущай обрезается, типа у нас веб — чего вы хотели?

                            Задача стоит чтобы строчки нормально переносились — с расширением высоты всей строчки. Тем более что перенос — только один из случаев когда в этих двух табличках будут строки по высоте отличаться. Может быть справа какую кнопку воткнули, в таблице разное суют, делать фиксированную высоту строкам — не самый гибкий вариант.

                            Мы решали тем, что ставили туда пустой div со скролл-баром, а при перемещении — прятали колонки. Да, так получается не плавно, но работает. Вот как сделать чтобы было и плавно, и разная высота — мы так и не придумали.

                            И эта задача с таблицей — не исключение, а скорее правило. Я за все виды приложений не скажу, но конкретно в случае оперденей из таблиц и форм, в вебе танцы начинаются прямо от входа.
                            • 0
                              Сейчас открыл демку, которая по ссылке. В этом случае да, чуть посложнее обычной таблицы, но в целом тоже можно решить не слишком геморроясь. Хотя хзхз.

                              Прошу прощения что глаза в одном месте и ссылку не сразу тыкнул.
                              • 0
                                Я решал и сильно геммороился, правда нам надо было IE6 поддерживать.
                  • +4
                    Мы любим. Спасибо.

                    Когда программирую на js испытываю особенное удовольствие. Вся эта асинхронность.
                    Ня!
                    • +11
                      Одни обожают JS за ассихнонность, а другие ненавидят JS за ассинхронность.
                      • +16
                        есть гораздо более удачные решения, нежели макароны колбэков и различные костыли, призывающих это обойти
                        • 0
                          Можно пример? Хочется узнать, чем люди пользуются
                          • +1
                            Люди пользуются promises, features and generators.
                            • +6
                              бинго!
                              правда все же futures
                              • +1
                                а некоторые извращенцы(я в хорошем смысле) — еще и icedCoffeeScript.
                                • 0
                                  Ради пары псевдомонад нет смысла мучать себя кофескриптом, если он не по душе. :) Есть, например, фейсбуковский Регенератор.
                            • +3
                              Я не могу сдержаться.
                              Erlang!
                            • +1
                              Async на сервере и на клиенте.
                            • +1
                              асинхронность JS зависит от того как движок используется в приложении.
                              В Node.JS и браузерах движок любят использовать как асинхронный, но ничто не мешает ему работать как полностью синхронный язык.
                              • 0
                                У меня есть мнение, что JS всё-таки не язык общего назначения. Круг задач на нём можно решать достаточно широкий, но не все решения будут выглядеть хорошо.
                                • +1
                                  под решениями я и подразумевал другие языки :D
                              • 0
                                Я где-то в середине пути от вторых к первым. Достаточно лишь начать уметь эту асинхронность «готовить».
                            • +64
                              Я не то чтобы супер профессионал в JS. Тем не менее несколько лет писал и пишу на нем достаточно сложные системы. Паралельно с этим очень много пишу на Python и балуюсь Go.
                              На мой взгляд, для действительно больших систем со сложно бизнес-логикой JavaScript отвратительный язык.
                              • –5
                                Сложные системы на js легче писать, чем генерить html (пусть и через всякие библиотеки) на сервере и всю логику хранить там.
                                Если б можно было я вообще ты только СУБД и браузер оставил, без веб-сервера.
                                • +4
                                  Сложные системы на js легче писать, чем генерить html

                                  Не то чтобы совсем не согласен с этим утверждением, однако не вижу большой разницы где «генерить html» на сервере или на клиенте, равзе что на клиенте можно чуть по гибче, но на сервере безопаснее.

                                  Если б можно было я вообще ты только СУБД и браузер оставил

                                  Если бы можно было, я бы был миллардером и жил на острове.
                                  • +1
                                    А что вам мешает оставить браузер и REST-сервисы? Ну и пишите себе на JS после этого что угодно.
                                    • –2
                                      Можно. Вот этим написать сервер. Плюс научить postgres общаться через http.
                                      • 0
                                        А, кто, простите, будет http-запросы обрабатывать? Только не говорите, что web-сервер. И еще, какие запросы сможет слать браузер к СУБД в вашей схеме? DELETE FROM very_important_data, к примеру, можно? Очевидно, что нет. Значит есть «разрешенные» запросы. И кто же будет это проверять? Ведь логики-то вы на сервере не оставили.
                                        • +1
                                          СУБД вполне может поддерживать логику типа управления правами доступа.
                                          • +5
                                            может, но не нужет
                                            • 0
                                              Втакой схеме, так скажем, нетривиальная логика будет. Да и авторизоваться надо как-то из полностью открытого кода через прозрачный канал.
                                              • –1
                                                А как сейчас авторизуются?
                                        • 0
                                          Соглашусь. Похожий опыт. Причём, на мой взгляд, JS был бы как минимум раза в полтора удобнее, если бы у него была «утиная» типизация, как в Python'е и разного рода лиспах.
                                          • +1
                                            Готово! В JavaScript есть duck typing.
                                            • +9
                                              Ну, я немного не так выразился. Помимо утиности, хотелось бы на 3+"3" получать TypeError, а не "33".
                                              • +6
                                                Минусующие, наверное, никогда не передавали по ошибке вместро строки в какую-нибудь функцию объект, который превращался затем в "[object Object]" и совершал долгий путь по коду, прежде чем привести к отложенным, но неприятным последствиям, таким, что даже с неплохим набором тестов далеко не сразу можно понять, в чём дело. А, или вот — случайно загнать строку вместо массива, а потом биться головой о стену, что где-то дальше по коду somevar[0] = ...; не даёт никакого эффекта.
                                                • +6
                                                  Это сильная типизация, а не утиная.
                                                  • +2
                                                    Да, верно. Я же говорю, я не так выразился. «Утиность» является стандартной характеристикой Python'кой системы типов, но не определяет строгость проверки типов. С другой стороны, если вы скажете, что в Python'е сильная типизация, вас очень многие поймут неправильно, т.к. многие путают сильную типизацию со статической.
                                                    • 0
                                                      То, о чем вы говорите называется type coercion.
                                                      • +3
                                                        Если быть конкретнее, то, что мне мешает жить в JS, называется implicit type conversion (coercion, typecasting, как угодно). А так выражение int(x) в py — тоже coercion, только explicit.
                                                        • 0
                                                          Я согласен, что это плохое решение. Но то же неявное конвертирование используется, например, в условии if.
                                                      • +2
                                                        С другой стороны, если вы скажете, что в Python'е сильная типизация, вас очень многие поймут неправильно, т.к. многие путают сильную типизацию со статической.

                                                        Так надо развеивать эти заблуждения, нет?
                                                      • +1
                                                        По моему чаще используют термин «строгая»
                                                        • +1
                                                          Строгая вообще не допускает неявного приведения типов, сильная допускает некоторые типа int к long int.
                                                      • +1
                                                        Хотите вредный совет?

                                                        delete Object.prototype.toString;
                                                        delete Object.prototype.valueOf;
                                                        delete Array.prototype.toString;
                                                        ...
                                                        

                                                        И будет вам счастье с TypeError.
                                                        Само собой, надеюсь, что никто это вместе с чужим кодом использовать не будет.
                                                • 0
                                                  • +1
                                                    Что доказывают ваши ссылки? Никто не говорит что на JS нельзя написать больших и сложных приложений. Моё утверждение что делать это на них сложнее чем на многих других языках.
                                                    • +2
                                                      Можно писать отвратительно на любом языке. А можно узнать тонкости и начать использовать язык по максимуму, используя сложившиеся паттерны. Причем тут ваш первый комментарий к JS?
                                                • +13
                                                  >Скажем, вы поделили на нуль, большинство языков выбросит ошибку и завершит работу, а JavaScript покажет знакомый нам Not a Number
                                                  Это в какой реализации JavaScript? Всегда было Infinity.
                                                  По спецификации Infinity имеет тип Number.
                                                  • +1
                                                    Поправил. Спасибо за внимательность.
                                                    • +19
                                                      Браво, даже сам автор статьи запутался в своем великолепном языке. Нет, конечно, путаются все и JS программисты и Java, и C#. Но сам факт показателен, что JS настолько продвинутый и раскрепощенный язык, что он не дает никаких гарантий по поводу поведения кода при неизбежных ошибках. Видимо, потому что этот язык разрабатывался для какого-то идеального мира где все программисты гуру, никогда не опечатываются и знают досконально поведение каждой команды. Правда вот, сам автор к этому миру не принадлежит.
                                                    • 0
                                                      Может автор делил нуль на нуль? Тогда получится действительно NaN.
                                                      • +1
                                                        Ну, или Inf на нуль. Или NaN ) В любом случае, к JS это имеет довольно опосредованное отношение.
                                                    • +7
                                                      О, я бы просто обожал JS, если бы не «коллбеки, коллбеки, коллбеки, коллбеки, коллбеки, коллбеки». На первых порах прикольно, а дальше становится всё более и более неприятно работать с этим языком.
                                                      • +3
                                                        В ES6 добавили генераторы, которые решают вашу проблема, и еще дозволяют централизированно обрабатывать ошибки. Правда, если вы пишете для браузеров, ждать придется еще долго.
                                                      • +2
                                                        откройте для себя async, коллбеки нынче меньшая из проблем js.
                                                        • 0
                                                          Вы, наверное, имели ввиду Q? В async как раз используются callback'и. github.com/kriskowal/q
                                                          • +1
                                                            Q уже не модно, сейчас в тренде Bluebird. Но AmdY скорее всего имел ввиду что async решает проблему каши из коллбеков
                                                            • 0
                                                              С async перестаёшь ненавидеть коллбеки и начинаешь их любить.
                                                          • +1
                                                            github.com/caolan/async
                                                            или deferred / github.com/kriskowal/q

                                                            Только немного настораживает, что async не обновляется уже несколько месяцев.

                                                            Для меня проблемой было то, что с первого взгляда неясно, является ли функция асинхронной или нет. Возвращает ли она значение в коллбеке? Или в return? Или она в return возвращает deferred-объект?
                                                            • 0
                                                              А что по-вашему там надо менять, учитывая что async просто работает? Изменения ради изменений никому не нужны…
                                                        • +13
                                                          А программы на C# и JavaScript параллельно разрабатывались? Какая из групп разработки выясняла неточности в требованиях и т.п.?
                                                          • –8
                                                            Команда C# начала на год раньше. В этом плане им, конечно, было сложнее, но конце мы их немного перегоняли.
                                                            • +16
                                                              Тогда совсем не удивительно. что результаты такие.
                                                              • +5
                                                                В группе из 12 программистов половина времени уйдёт только на совещания, пока все между собой договорятся :)
                                                            • +6
                                                              Все эти слова применимы, например, к Perl.

                                                              Но вообще, JS крайне любопытен.
                                                              • +32
                                                                Это какая-то слишком холиварная статья. Ничего нового про JavaScript я не узнал, доводы меня не убедили. Думаю для бэкендщиков это не доводы.
                                                                • +11
                                                                  Вот я сейчас рискую получить звание «Капитан Очевидность», но все-таки скажу, что для каждой задачи есть свой инструмент (в данном случае язык программирования).
                                                                  • +12
                                                                    Мне кажется что автор действительно достиг больших высот в JavaScript и познал дао его инфраструктуры (я без сарказма). За 10 лет это вполне достижимо. Поэтому и любит его.

                                                                    Но у большинства разработчиков к этому языку все таки больше претензий.
                                                                    • –2
                                                                      Раз уж затронул специфику JS, то где хоть слово про область видимости переменных, про то что null в JS это объект? Ничего про эти и другие специфичные для JavaScript вещи, которые стоит узнать прежде чем начать на нем писать.
                                                                      • +2
                                                                        Написано же — «мы считаем, что все, кто работают над кодом — профессионалы и доверяем им».
                                                                        • +1
                                                                          null не объект.
                                                                          А про typeof null == 'object' можно почитать в стандарте, если на пальцах то тут habrahabr.ru/post/159313/
                                                                          • +1
                                                                            Я знаком со статьей, как раз про эту «специфику» языка и говорил
                                                                        • –1
                                                                          Хочу заметить, что в тексте ни слова про замыкания. Не уж то это случайность?
                                                                          • +2
                                                                            Считал замыкания интуитивно понятным принципом. К тому же они есть во многих популярных языках (PHP, C#).
                                                                            • 0
                                                                              Субъективно, они там ещё не начали массово использоваться, а для JS — єто норма давно.
                                                                              • +1
                                                                                Оооочень субъективно. В C# замыкания мейнстрим с 3-ей версии, т.е. с 2007-го года, а появились они там во второй версии, т.е. с 2005-го.
                                                                                • 0
                                                                                  А в джаваскрипте с какого?
                                                                                  • 0
                                                                                    А это не важно, важно что они сейчас уже массово используются.
                                                                                • +1
                                                                                  Это как это не начали? Где лямбды — там и замыкания. Лямбды в C# используются в хвост и в гриву. Далеко не все на нем пишут как на джаве.
                                                                              • 0
                                                                                Сложно представить язык, где функции — обьекты первого класса, и нет поддержки замыканий. Как правило, если есть поддержка первых, вторые идут «из коробки».
                                                                              • +33
                                                                                Скажем, вы поделили на нуль, большинство языков выбросит ошибку и завершит работу

                                                                                Нет если это деление чисел с плавающей точкой. На этот счёт есть IEEE 754.
                                                                                Выход из строя одного элемента не выводит из строя всю систему. Конечно, плохо показывать пользователю NaN или undefined, но это гораздо лучше, чем аварийно завершиться, как все мы много раз видели у многих нативных прогамм под Windows (и не только).

                                                                                Вывод из строя одного элемента обязан обрушить всю систему, если явно не указано иначе (т.е. если исключение не поймано). Иначе мы получаем неопределённое поведение во всей программе и потенциально портим пользовательские данные. Выпасть с ошибкой — лучше. Поэтому нужно явно проверить результат на NaN. Если вся программа — 3 строчки, то это не так страшно, но сейчас javascript используется далеко не только для «динамического HTML».

                                                                                JS — не такой плохой язык, но именно этот момент — скорее слабая сторона.

                                                                                Если говорить об Объектно Ориентированном Программировании

                                                                                то у нас как минимум есть замыкания, которые, как известно, poor man's объекты. А объекты — poor man's замыкания. Если ещё к ним прилагаются прототипы — тем лучше.

                                                                                P.S.: Javascript — не единственный язык с динамическими типами и на Javascript/Java/C# выбор языков не заканчивается. И чаще строгая типизация (в том числе строгая динамическая, пример — тот же Python) лучше, чем слабая как в Javascript: явное приведение типов намного проще отлаживать. Поэтому в реальности программы на javascript нечасто бывают длинными.

                                                                                Есть возможность включить статическую типизацию (тот же asm.js), но строгую — нет. Иногда проще было бы с ней.
                                                                                • –7
                                                                                  Вывод из строя одного элемента обязан обрушить всю систему

                                                                                  Даже если это сервер?
                                                                                  • +22
                                                                                    Необработанное исключение? Обязан особенно если это сервер. Он же перезапустится (и его работу на время перезапуска возьмут на себя другие узлы если нужна безотказность). Это намного лучше, чем написать чушь в базу. Тем более учитывая, что ошибка может быть спровоцированна неожиданными вещами на входе (в результате целенаправленной атаки).
                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                      • +8
                                                                                        Почти так, но бектрейсом не стоит плевать в пользователя. Это слегка небезопасно. В лог — пожалуйста.
                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • +38
                                                                                      Скажем, вы поделили на нуль, большинство языков выбросит ошибку и завершит работу, а JavaScript покажет знакомый нам Not a Number и, возможно, даже выведет его в интерфейс пользователю в виде строки, если так задумана логика программы. Хорошо это или плохо? Я бы сказал, это позволяет создавать программы с высочайшим уровнем стабильности.

                                                                                      В корне неверное утверждение. Если произошла ошибка, рантайм должен как можно раньше сообщить об этом. Если же ошибки тихо игнорируются, значения конвертирутся и передаются дальше, то проблема может быть не видна ещё час, день, месяц. А потом вдруг вылезити в совершенно неожиданном месте и поломать гораздо больше. Или даже хуже — продолжать работать, но выдавать неверные данные, подрывая работу всей организации.
                                                                                      • +1
                                                                                        Я согласен что ратайм ошибки можно игнорировать. Но! Только осмысленно, и на уровне определенного блока кода. Блок может быть и маленьким и большим, не важно. И этот блок должен быть завернут в try catch, чтобы искверканные рантайм ошибкой данные никтогда не покинули этот блок.
                                                                                        • –18
                                                                                          Да, это популярное мнение. Не хочу вступать в холивар, просто небольшой контраргумент: то что вы написали хорошо в релизе для разработчиков и тестировшиков, в продакшн-коде часто лучше всё-таки умолчать об ошибке. Пусть вы её быстро увидите, а так же её увидит приличная доля ваших пользователей, это ударит по репутации сервиса и менеджменту будет не важно какими благими намерениями вы руководствовались. При графике релизов раз в неделю или две, что сейчас всё более популярно, сложно гарантировать абсолютно стабильный код. Однако лучше если в службу поддержки придёт 2 обращения, чем 200. В любом случае ошибка будет исправлена, если нет — значит она не так критична. Этот подход хорошо подходит к разработке интерфейсов, если вы работаете с финансами или сложной математикой — возможно ваш подход более оправдан, хотя в JavaScript для таких случаев тоже можно вставить дополнительные проверки.
                                                                                          • +16
                                                                                            в продакшн-коде часто лучше всё-таки умолчать об ошибке.

                                                                                            После чего пользователь будет задавать вопросы «где мои данные» (реальный пример из опыта, когда js-ошибка проглатывалась, и табличка в браузере оставалась пустой)
                                                                                            • 0
                                                                                              Если есть ошибка — пользователь будет недоволен в любом случае. И, как я понимаю, обращение пользователя с вопросом про данные помогло вам найти и устранить ошибку не хуже, тем если бы ему выводилось что-то вроде «General failure».
                                                                                              • +5
                                                                                                Вы поняли неправильно. Отсутствие данных в гриде — возможное поведение системы, поэтому один пользователь, который данных не видит, считает, что система работает, и звонит другому пользователю, который должен данные вводить, с вопросом «какого хрена ничего не сделано». Тот в холодном поту бросается к экрану и — поскольку он считает, что система работает нормально — в панике звонит начальству со словами «все данные пропали». Дальше это эскалируется и долетает до разработчиков как критический баг «все пропало».

                                                                                                А если бы там было сообщение об ошибке, (а) не было бы паники и (б) разработчики бы сразу знали, где искать ошибку, а не разбирались бы в состоянии БД и логике выборки данных.
                                                                                            • +14
                                                                                              При подходе который я предлагаю программа в случае ошибки выдаст что то типа «Ошибка при расчете стоимости заказа», но не упадет целиком. Так как вы предлагаете, программа выдаст какую нибудь жуть типа «На вашем счету NaN рублей, вы сделали undefined заказов, ваш долг составляет -1.51e-28 рублей». И еще и сохранит это на сервере.
                                                                                              • –2
                                                                                                Если есть время — конечно лучше создать отдельные сообщения для ошибок, я с этим не спорю, и в JavaScript это нисколько не сложнее. Скажем в C++ вы будете использовать try catch, а в JavaScript проверете все выводимые значения на NaN и Infinity при рендеринге.
                                                                                                • +1
                                                                                                  Ужас… А если значения будут выводиться через месяц? Кто и когда и как будет искать почему там NaN и Infinity?
                                                                                          • +10
                                                                                            JavaScript хороший язык, в основном благодаря HOF и замыканиям, но в вашей статье слишком много слов в превосходной степени.

                                                                                            Свойства делают публичными потому, что сделать их приватными не так уж и просто. Нужно объявлять все методы на инстансе, а не на прототипе, что влияет на прозводительность и потребление памяти. Кроме того, нету промежуточного уровня — protected, который много используют в других языках, и поэтому если вы хотите, чтобы ваш «класс» наследовался, приходится использовать properties.

                                                                                            Благодаря системе типов можно избежать целого класса runtime ошибок, правда, за счет более сложного процесса разработки. Например, если ваша программа на Haskell, который известен своей системой типов, скомпилировалась, с большой вероятностью она будет работать как ожидается.

                                                                                            Синтаксис языка во многом похож на C, что вводит многох людей в заблуждение. JavaScript сильно отличается от того, к чему вы привыкли, если писать на нем как на C, будете наступать на разнообразные грабли типа variables hoisting или обработки ошибок в асинхронных коллбеках.

                                                                                            К синтаксису у меня вообще большие претензии, но coffeescript решает почти все.

                                                                                            Вот еще парочка вещей, которые мешают мне любить JavaScript: почему тип null'а это object; почему arguments это как массив, но не массив; почему так сложна логика использования this?
                                                                                            • +2
                                                                                              Обилие array-like штук (arguments, NodeList) объясняется очень просто: в первой версии языка не было массивов. Из первой же версии тянется баг с typeof null.
                                                                                              • –4
                                                                                                А вас не пугает что одинаковые буквы произносятся по разному в различных языках?
                                                                                                • 0
                                                                                                  Вы о слове коллбек? Да, вы правы, извините.
                                                                                                  • 0
                                                                                                    Что вы, нет, я про:
                                                                                                    Синтаксис языка во многом похож на C, что вводит многох людей в заблуждение. JavaScript сильно отличается от того, к чему вы привыкли, если писать на нем как на C, будете наступать на разнообразные грабли типа variables hoisting или обработки ошибок в асинхронных коллбеках.
                                                                                                • 0
                                                                                                  Ну вот что за убеждение такое что методы нужно объявлять на инстансе?! =) Вот так можно сделать на ES6, ещё в комментариях к той статье я указал как почти тоже можно сделать на ES5 (ну или на ES3, тоже можно). Я отправляю в комментарии, потому что хочу предупредить — для ES5 нужно самостоятельно очищать память (что в общем-то тоже просто).
                                                                                                  • 0
                                                                                                    Очень красивое решение с WeakMap, я в восторге. У вашего же метода будут проблемы с памятью — данные не удалятся с массивов при сборке мусора.
                                                                                                    • 0
                                                                                                      Кстати, Nicholas описал практически такое же решение, но с одним массивом в разделе «Towards truly private members».
                                                                                                      • 0
                                                                                                        Все понятно про то что Николас описал — я таким давно уже пользуюсь, но мое решение все же не такое. И объясните мне кто-нибудь наконец что такого в том чтобы добавить метод dispatch в прототип в моем решении и очистить память вручную? Лишняя стока в коде так сильно усложняет жизнь? =)
                                                                                                    • 0
                                                                                                      В ES6 для создания приватных свойств есть символы. В свежем хроме они уже доступны. Они не полностью приватны (есть Object.getOwnPropertySymbols), но, пожалуй, это идеологически более правильное решение. Касательно вашего комментария — вместо использования массивов проще эмулировать WeakMap'ы храня данные на ключе — нет необходимости чистить и не течет (пока существует коллекция).
                                                                                                      • 0
                                                                                                        Спасибо за символы, посмотрю. А насчет эмуляции WM вы что имеете в виду? Не это же?
                                                                                                        • 0
                                                                                                          Именно эмуляцию WeakMap с хранение данных на ключе. В примитивном виде будет что-то в стиле

                                                                                                          if(!window.WeakMap){
                                                                                                            var id  = 0
                                                                                                              , has = ({}).hasOwnProperty
                                                                                                              , WEAKDATA = Math.random().toString(36).slice(2);
                                                                                                            window.WeakMap = function(){
                                                                                                              if(!(this instanceof WeakMap))throw TypeError();
                                                                                                              this.clear();
                                                                                                            }
                                                                                                            WeakMap.prototype.clear = function(){
                                                                                                              this._id = id++;
                                                                                                            }
                                                                                                            WeakMap.prototype['delete'] = function(key){
                                                                                                              return this.has(key) && delete key[WEAKDATA][this._id];
                                                                                                            }
                                                                                                            WeakMap.prototype.has = function(key){
                                                                                                              return (key === Object(key)) && has.call(key, WEAKDATA) && has.call(key[WEAKDATA], this._id);
                                                                                                            }
                                                                                                            WeakMap.prototype.get = function(key){
                                                                                                              return (key === Object(key)) && has.call(key, WEAKDATA) ? key[WEAKDATA][this._id] : undefined;
                                                                                                            }
                                                                                                            WeakMap.prototype.set = function(key, value){
                                                                                                              if((key !== Object(key)))throw TypeError();
                                                                                                              (has.call(key, WEAKDATA) ? key : Object.defineProperty(key, WEAKDATA, {value: {}}))[WEAKDATA][this._id] = value;
                                                                                                              return this;
                                                                                                            }
                                                                                                          }
                                                                                                          

                                                                                                          Честную и полностью не текущую эмуляцию WeakMap на ES5 создать нельзя. Минус данной — после удаления коллекции или её очистки через .clear, ключ и значение останутся связанными. Но для данного случая — хранения приватных полей — никаких минусов, утечек и необходимости чистить.
                                                                                                          Символы эмулировать еще проще, но из-за того, как и за счет чего это делается, я бы их эмуляцией пользоваться не стал.
                                                                                                  • –1
                                                                                                    Порой вы не можете быть уверены даже в том, какие методы имеет тот или иной объект.

                                                                                                    Вы можете вывести полное содержание практически любого объекта в консоль, со всеми его методами, значениями полей, цепочкой прототипов и т.д. Хотя это, конечно, относится не к JS как таковому, а к инструментам разработчика, которые, однако, де-факто стандарт при разработке на этом языке.
                                                                                                    • +3
                                                                                                      в общем идеализированно, но идейно я с вами.
                                                                                                      • +3
                                                                                                        Подобные восхваления можно написать практически про любой язык. Вот, уже упомянутый C#: ООП вместе с лямбда-функциями, dynamic, async / await и т.д. и т.п. Тут уж кто к чему привык)
                                                                                                        • +43
                                                                                                          Статья похожа на рассказ какого-то сетевого маркетолога.

                                                                                                          Боль и кровь десятилетий разработчиков, приложивших руку к строгим стандартам языка, просто тлен по сравнению с функционалом JavaScript.
                                                                                                          Конечно, и миллионы людей могут ошибаться, но строгая стандартизация языков однозначное, строго выверенное и на практике проверенное решение.

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

                                                                                                          Ну и выражения в одном тексте вроде
                                                                                                          JavaScript обладает очень низким порогом входа.
                                                                                                          и
                                                                                                          Это требует высокого уровня концентрации и хорошего понимания архитектуры.
                                                                                                          убедительно показывают, что количество аргументов здесь решает больше, чем их сочетаемость и актуальность.
                                                                                                          • –4
                                                                                                            Скажем, вы поделили на нуль, большинство языков выбросит ошибку и завершит работу, а JavaScript покажет знакомый нам Not a Number

                                                                                                            Скорее большинство компилируемых языков выкинет ошибку (и то, только в случае целочисленных типов), а интерпретируемые и выкидывают либо INF (если деление на ноль) или NaN (в случае того-же sqrt(-1)), что, так-же, выкинут компилируемые, в случае представлении числа по IEEE 754.
                                                                                                            • +1
                                                                                                              Кому-то нравится порядок в типах c#, кто-то обожает гибкость, присущую javascript. И у тех, и у других — получается хорошо решать стоящие перед ними задачи (при условии их профессионализма, виртуозного владения основами и тонкостями языка).

                                                                                                              Но самое жуткое, что мне пришлось наблюдать в одном из прошлых проектов — это как заядлые (в хорошем смысле слова) шарписты воссоздавали типизацию, классы, публичные, приватные и защищенные методы в javascript, чтобы подчинить этот язык более привычной им логике. Они плодили оъекты «классов» через new ..() и, не зная, как их связывать, создавали древовидные структуры, чтобы содержать эти объекты. Поддержка такой системы оборачивалась совершенно непредсказуемыми косяками и была доступна не то, что «дот-нетчикам с элементарными знаниями javascript», и даже не сугубо джаваскриптерам, а преимущественно самим создателям. В общем, удручающее воспоминание.

                                                                                                              По возможности удерживайтесь от такой крайности. Дружите с языками по отдельности.

                                                                                                              • +28
                                                                                                                Большинство языков ставят ограничения, якобы для нашего же блага. JavaScript не признаёт ограничений, вы можете менять код где угодно и когда угодно, в том числе гибко патчить чужой код.

                                                                                                                В JavaScript нет защиты от дурака. Мы считаем, что все, кто работают над кодом — профессионалы и доверяем им.

                                                                                                                Я бы сказал, это позволяет создавать программы с высочайшим уровнем стабильности. Выход из строя одного элемента не выводит из строя всю систему.

                                                                                                                Статья просто дышит юношеским максимализмом и духом rockstar programming. Я тоже думал нечто подобное на 2 курсе и хотел создать свой собственный язык с похожими возможностями. Ничего, после работы над более-менее серьезным проектом, желание «гибко патчить чужой код» сразу же отпадает, равно как и убежденность в профессионализме окружающих.
                                                                                                                • +10
                                                                                                                  Если вы знакомы с C++ или Java, то можете начать вполне сносно программировать на нём уже через 15 минут после знакомства.
                                                                                                                  Ага. Только что то не хочется.
                                                                                                                  • +1
                                                                                                                    О, JS тред?
                                                                                                                    А можете мне объяснить, почему этот код работает именно так, а не иначе?
                                                                                                                    • –1
                                                                                                                      Да. Это же очевидно. Плюс в статье это оговаривается.
                                                                                                                      • 0
                                                                                                                        Плюс в статье это оговаривается.

                                                                                                                        Что-то не нашел, где конкретно? Можете привести цитату?
                                                                                                                        • +2
                                                                                                                          '3' + 2 === '32';

                                                                                                                          Я это имел ввиду.
                                                                                                                          • 0
                                                                                                                            А, я другое в виду имел: почему индекс массива (который по логике должен быть числом) в данном примере является строкой? Чем руководствовались разработчики языка реализовав именно такое поведение?
                                                                                                                            • +1
                                                                                                                              Добавлю:
                                                                                                                              — почему в i попадает индекс, когда для такого написания во многих (как минимум) других языках характерна «for each» конструкция, при которой в i должно попадать значение массива
                                                                                                                                • +3
                                                                                                                                  Да нет, тут проблема не в понимании матчасти, тут проблема в «схожести» с другими языками визуально с совершенно иным смыслом:
                                                                                                                                  — там, где в других языках идёт foreach по элементам массива
                                                                                                                                  — в JS идёт foreach по ключам ассоциативного массива свойств объекта.
                                                                                                                                  Такое поведение рождает непонятки, вопросы и претензии к языку.

                                                                                                                                  Так что, если при обычном программировании можно (пытаться) опираться на стек языков, при работе с JS придётся или тратить дополнительное время на внимательное и вдумчивое написание (чтобы не налететь на такие вещи), либо придётся отказаться от других языков… Иная альтернатива — писать говнокод.
                                                                                                                                  • 0
                                                                                                                                    Так что, если при обычном программировании можно (пытаться) опираться на стек языков, при работе с JS придётся или тратить дополнительное время на внимательное и вдумчивое написание

                                                                                                                                    Точно так! C JS я сталкиваюсь очень эпизодически (основные языки: Python, C++, C), поэтому и обратил внимание на то, что когда пытаешься сделать что-либо наиболее очевидным путем (без предварительного штудирования манов), то часто натыкаешься на странности.
                                                                                                                              • +4
                                                                                                                                Я может быть сейчас вам тайну открою, но цикл for-in в js не предназначен для обхода массива. Он не гарантирует вам очередность прохода. Он предназначен для обхода свойств объекта. В 6-ой версии для обхода массива предназначается for-of.
                                                                                                                                • 0
                                                                                                                                  > Он не гарантирует вам очередность прохода.
                                                                                                                                  Ну об этом я как раз в курсе. Собственно, одна из причин почему в JS используются конструкции вида [{ key: 'first', value: 'foo' }, { key: 'second', value: 'bar' }]
                                                                                                                                  • 0
                                                                                                                                    Где такие конструкции используются?
                                                                                                                                    • –2
                                                                                                                                      Там где нужно реализовать нормальные хэши (с возможностью использовать произвольные значения ключей) которые ведут себя именно как хэши. Если делать в лоб используя { first: 'foo', second: 'bar' } — то можно запросто сломать внутренности языка в случае наличия приходящих извне данных:

                                                                                                                                      > a = {}
                                                                                                                                      Object {}
                                                                                                                                      > typeof(a.valueOf)
                                                                                                                                      «function»
                                                                                                                                      > user_controlled = 'valueOf'
                                                                                                                                      undefined
                                                                                                                                      > a[user_controlled] = 31337
                                                                                                                                      31337
                                                                                                                                      > typeof(a.valueOf)
                                                                                                                                      «number»
                                                                                                                                      • +1
                                                                                                                                        В лоб, конечно, не стоит, но и говнокодить тоже не надо. Потому что получается не хэш, а хрен знает что с линейным временем доступа и с повышенным расходом памяти. Лучше просто добавлять префикс какой-нибудь, чтобы исключить конфликт имен: {x_first: 'foo', x_second: 'bar'}. И всё будет хорошо. P.S. Это, конечно, не решает проблемы порядка обхода.
                                                                                                                                        • +2
                                                                                                                                          Это, конечно, не решает проблемы порядка обхода.

                                                                                                                                          Да там куча всяких проблем, например, в вашем случае прийдется пилить .length что бы была возможность получить ко-во элементов хэша, итд.
                                                                                                                                          Тут дело не в том как более правильно обходить подобные грабли языка, а в том что сам факт их наличия мешает.
                                                                                                                                • +1
                                                                                                                                  Потому, что for...in — итератор по ключам объекта, а ключи объектов — это строки. Массив тоже объект, если что. В ES6 добавили for...of
                                                                                                                                  developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
                                                                                                                          • +1
                                                                                                                            i — это ключ. И переменная имеет тип String.
                                                                                                                            В JS массив это объект. Поэтому его можно итерировать.
                                                                                                                            • –5
                                                                                                                              i — это индекс массива, вам не кажется, что он не зависимо от содержимого массива по определению должен являться числом но никак не строкой?
                                                                                                                              • +5
                                                                                                                                Да нет же. Здесь это индекс массива.

                                                                                                                                for(var i = 0; i < arr.length; i++){}
                                                                                                                                

                                                                                                                                А здесь это ключ хеша.

                                                                                                                                for(var i in arr){}
                                                                                                                                

                                                                                                                                Это же очевидно.
                                                                                                                              • 0
                                                                                                                                Даже если

                                                                                                                                var arr = [1,2,3];
                                                                                                                                

                                                                                                                                В

                                                                                                                                for(var i in arr){}
                                                                                                                                

                                                                                                                                Все равно строка будет. Проверьте.

                                                                                                                                var arr = [1,2,3];
                                                                                                                                for(var i in arr){
                                                                                                                                  console.log(typeof i);
                                                                                                                                }
                                                                                                                                

                                                                                                                                • +4
                                                                                                                                  Тут дело в капитальном непонимании матчасти.

                                                                                                                                  for (var index in arr) {}
                                                                                                                                  эквивалентно
                                                                                                                                  for (var prop in obj) {}


                                                                                                                                  А бегать по массиву таким образом не советуют, потому что можно зацепить length.
                                                                                                                                  Для таких целей есть Array.prototype.forEach.
                                                                                                                                  • +8
                                                                                                                                    > А бегать по массиву таким образом не советуют, потому что можно зацепить length.

                                                                                                                                    Как раз length нельзя зацепить, он не Enumerable, а вот другие Enumerable свойства, в том числе из Array.prototype, могут.
                                                                                                                              • +3
                                                                                                                                Ох… В своё время забил на этот брейнфак и начал писать my_array.map(...) или my_array.forEach(...)
                                                                                                                                • 0
                                                                                                                                  …или my_array.every(), или my_array.filter(), или my_array.reduce(), или my_array.reduceRight(), или my_array.reduce(), или my_array.some()

                                                                                                                                  И это правильно. Потому что библиотечные функции (вкомпилированные в движок) работают, естественно, быстрее, чем цикл, запрограммированный на джаваскрипте.
                                                                                                                                  • 0
                                                                                                                                    Если бы они были нативными.
                                                                                                                                    На данный момент реализация подобных функций в V8 выглядят как «цикл, запрограммированный на джаваскрипте», при этом никак не оптимизированный. А это значит, что callback-и этих методов создаются и выполняются точно так же, как обычные функции, которых вообще нет в обычном цикле.

                                                                                                                                    Так что я бы пока не стал отказываться от for и while в критичных местах.