Обратите внимание, что все мои аргументы основаны на реальных вариантах использования. Встречные аргументы, которые не могут быть подкреплены примером использования в реальных, полных, интересных, полезных приложениях, недопустимы. Я видел маленькие «языковые демонстрации», которые есть у всех остальных, я видел посты в блоге, подробно рассказывающие о том, как прототипы и динамическая типизация делают какой-то тривиальный маленький пример на несколько строк короче, чем это было бы в C #, но они просто не актуальны к проблемам, с которыми вы сталкиваетесь при написании реального
кода, а не микродемонстраций и игрушек. Итак, вот мои проблемы с JS:
а) магия "это". Это так, кроме случаев, когда это так. JavaScript заставляет вас использовать анонимные функции повсеместно, за исключением того, что они всегда теряют надлежащий контекст для переменной «this», так что вы в конечном итоге получаете глупый код типа «var _this = this» повсеместно, а затем используете его внутри ваших обратных вызовов или других функций. В некоторые дни я клянусь, что количество функций, которые мне удается написать, которые не используют переименованное «this», на самом деле меньше, чем число, которое делает.
б) 1 + «1» - 1 = 10. Также «1» + 0 = «10». Да, это на самом деле вызвало ошибки в наших приложениях, где данные, которые должны быть числами, были загружены из файла JSON в виде строки из-за ошибки в другом приложении, и результат был не очень хорошим. Весь наш код загрузки пришлось обновить, чтобы добавить массу преобразований типов повсюду. Когда мне нужно, чтобы что-то было числом, я действительно волнуюсь, просто хочу, чтобы это было число, а не строка, или объект, или ноль, или что-то еще. Lua, который во многих отношениях очень похож на JavaScript, исправил эту проблему, просто не будучи достаточно отсталым, чтобы использовать один и тот же оператор для сложения и объединения строк.
в) глобальные переменные по умолчанию. Поэтому, даже если вы возьмете аргумент, что динамическая типизация просто «проще», потому что вам не нужно думать о объявлениях переменных, JavaScript выбрасывает этот аргумент в окно, заставляя вас ставить 'var' перед новыми идентификаторами повсюду , А потом он молча винит тебя, если забудешь.
г) Прототипы вместо классов. Существует очень мало крупных реальных JavaScript-приложений, которые не подключают свою собственную систему классов, чтобы обойти присущую бесполезность прототипов в архитектуре больших приложений. Те же самые приложения минимально используют прототипы для расширения базовых типов JavaScript, и только потому, что JS был настолько плохо спроектирован, что даже двум интересным встроенным типам, с которыми он поставляется, не хватает половины функций, которые вы ожидаете от них.
e) Невозможность создания типов передачи по значению. На самом деле это частая проблема почти на каждом языке, кроме C ++ / D. Для тех, кто использует JavaScript для написания приложений WebGL, взгляните на все библиотеки линейной алгебры для JavaScript. В 3D-приложениях вы почти используете векторы чаще, чем скаляры. Представьте, что каждое целое число в вашем приложении было передано по ссылке, так что «a = 1; b = a; b ++» делало a и b равными 2. Каждый маленький трехкомпонентный вектор является полным полным объектом. Они передаются по ссылке (на самом деле источник почти половины ошибок в нашей игре на WebGL). Они существуют в большом количестве, распределяются по куче и собирают мусор, что оказывает сильное давление на GC, что может и приводит к паузам GC даже в простых играх WebGL, если разработчик не перепрыгнет через нелепо сложные обручи, чтобы избежать создания новых векторов во всех местах, где логично создавать новые векторы. Вы не можете иметь перегрузку операторов, поэтому у вас есть очень большие и некрасивые выражения для выполнения основных операций. Доступ к отдельным компонентам происходит медленно. Объекты изначально не упакованы и, следовательно, невероятно медленно помещаются в буфер вершин, если только вы не реализуете их как экземпляры Float32Array, что в настоящее время приводит в замешательство оптимизаторы V8 и SpiderMonkey. Я упоминал, что они переданы по ссылке? Доступ к отдельным компонентам происходит медленно. Объекты изначально не упакованы и, следовательно, невероятно медленно помещаются в буфер вершин, если только вы не реализуете их как экземпляры Float32Array, что в настоящее время приводит в замешательство оптимизаторы V8 и SpiderMonkey. Я упоминал, что они переданы по ссылке? Доступ к отдельным компонентам происходит медленно. Объекты изначально не упакованы и, следовательно, невероятно медленно помещаются в буфер вершин, если только вы не реализуете их как экземпляры Float32Array, что в настоящее время приводит в замешательство оптимизаторы V8 и SpiderMonkey. Я упоминал, что они переданы по ссылке?
е) Нет встроенного включения или требуют функциональности. Серьезно, до сих пор. Сторонние библиотеки существуют, но почти во всех из них есть какая-то ошибка или другая, не в последнюю очередь это сбивает с толку проблему кеширования, по крайней мере, в Chrome, что затрудняет выполнение реальных разработок.
г) Динамическая типизация. Да, я готов начать этот спор. Вы начинаете замечать это чаще всего, как только перестаете писать маленькие веб-приложения или веб-страницы и начинаете писать большие приложения, в которых у вас действительно есть данные, которые сохраняются дольше, чем один щелчок мыши или цикл запроса / ответа: добавьте неправильный тип объекта к массив для последующей обработки и последующий сбой из-за отсутствующего метода или члена в совершенно ином фрагменте кода, чем там, где была настоящая ошибка. Веселые времена. Да, Java заставляет статическую типизацию казаться злой. Нет, Java / C # / C ++ - не единственный способ статической типизации. Вывод типа, неявная привязка интерфейса и т. Д. Дают вам все преимущества «простой в обращении и не много нажатий клавиш» динамической типизации без всех ошибок. Фактически, второй по популярности веб-язык - ActionScript 3 - статически типизирован, хотя в остальном он идентичен JS / ECMAScript. Кроме того, я получаю больше сбоев от приложений Python на моем рабочем столе Fedora, чем от приложений C / C ++ (на самом деле, ни одно из приложений C / C ++ на моем рабочем столе не работает, теперь, когда я об этом думаю). Отсутствие исключений для членов == так проще разрабатывать и поддерживать приложения, верно?
з) скорость. Да, большое количество разработчиков с очень плохой задницей приложило немало смехотворных усилий для того, чтобы сделать JS почти наполовину быстрее, чем компилятор с низким классом C, который мог бы написать один колледж Junior за несколько лет. месяцы. И LuaJIT находится в той же лодке, что и JS с точки зрения фундаментальных языковых ограничений, но в любом случае ему удается работать лучше, чем любая реализация JavaScript. Люди, которые не понимают, что на самом деле делают все JS-оптимизации в V8Я хотел бы заявить, что JS может делать удивительные вещи по скорости, но реальность такова, что все эти оптимизации в основном просто «очень-очень стараются проанализировать код, чтобы выяснить типы для переменных, а затем скомпилировать его, как слегка отсталый статически типизированный компилятор языка сделает это ". Да, и есть трассировка, но затем трассировка также работает на статически типизированных языках (и работает лучше из-за отсутствия необходимости в средствах защиты типов в сгенерированном машинном коде). На самом деле, ни одна из этих оптимизаций whizbang не была изобретена JS или для нее; большинство было взято из исследовательских JVM (Java - это зло!) или классических ООП-языков (прототипы потрясающие!).
я) IntelliSense даже не возможно. Хотите посмотреть, какие методы существуют для этой переменной, которая есть в строке 187 файла foo.js в вашем текстовом редакторе? Печалька. Проследите код, пока не выясните, где он был инициализирован, затем проследите код, чтобы выяснить, что на нем находится его прототипом. И потом надеюсь, что нет кода, динамически изменяющего прототип за вашей спиной. На самом деле, просто запустите его в браузере и установите точки останова, потому что узнать что-либо полезное о значении любым другим способом в принципе невозможно для любой базы кода больше, чем сайты toy_web_app.html, которые апологеты JavaScript используют для прославления простоты и простоты JavaScript. Некоторые редакторы кода очень стараются сделать лучше, и почти что-то вроде успеха получается в действительно простых случаях, иногда, однажды.
к) нет преимущества. JavaScript даже не особенный по сравнению с другим динамически типизированным языком. Он вообще не способен делать что-либо интересное, что также не может быть сделано Lua, Python, Ruby и т. Д. Ни одна из реализаций JS не является более быстрой, чем LuaJIT или PyPy или другие различные расширенные реализации JIT других динамических процессов. языки. У JS нет плюсов по сравнению с другими общедоступными языками. О, за исключением того, что он работает изначально в веб-браузере без плагина. Что является единственной причиной в мире, почему это так популярно. Фактически, это единственная причина, по которой событие существует, Если кто-то 10 лет назад только что подумал: «Черт, давайте добавим в наш браузер хорошо продуманный и хорошо зарекомендовавший себя язык и заставим других делать то же самое, вместо того, чтобы заставлять всех использовать этот маленький глупый хакджоб, который придумал NetScape». "Интернет будет выглядеть совсем иначе (лучше) сегодня. Представьте себе будущее, если Chrome поместит Python в Chrome как поддерживаемый язык. Или на самом деле, представьте себе: Google добавляет C / C ++ в Chrome как поддерживаемый язык (http://code.google.com/p/nativeclient/).