Зауважте, що всі свої аргументи я базую на реальних випадках використання. Контраргументи, які неможливо підкріпити прикладом використання в реальних, повних, цікавих, корисних програмах, недійсні. Я бачив маленькі "мовні демонстрації" у всіх інших, я бачив повідомлення в блогах, де детально описується, як прототипи та динамічний набір тексту роблять тривіальний маленький приклад на кілька рядків коротшим, ніж це було б у C #, але вони просто не мають значення до проблем, з якими ви стикаєтесь із написанням реального
коду, а не мікродемонстрацією та іграшками. Тож ось мої захоплення JS:
а) Чарівне «це». Це це, за винятком випадків, коли це так. JavaScript підштовхує вас до використання анонімних функцій по всьому місцю, за винятком того, що вони завжди втрачають відповідний контекст для змінної 'this', тож у вас все-таки є кодовий код типу "var _this = this", а потім використовується всередині зворотних викликів або інших функцій. Деякі дні я клянусь, що кількість функцій, які мені вдається записати, які не використовують перейменований "цей", насправді менша, ніж кількість.
б) 1 + "1" - 1 = 10. Також "1" + 0 = "10". Так, це насправді спричинило помилки для наших додатків, коли дані, які, як очікується, буде число, завантажувались з файлу JSON як рядок через помилку в іншій програмі, і результат був не гарним. Весь наш код завантаження довелося оновити, щоб додати тонну перетворень типів у всьому світі. Коли мені потрібно, щоб щось було число, я справді боюся, я хочу, щоб це було число, а не рядок чи об'єкт, нуль чи щось інше. Lua, яка в багатьох відношеннях дуже схожа на JavaScript, вирішила цю проблему, просто не вистачивши на відсталість, щоб використовувати того самого оператора для додавання та конкатенації рядків.
в) глобальні за замовчуванням змінні. Тож навіть якщо ви приймаєте аргумент, що динамічне введення тексту просто "простіше", тому що вам не потрібно думати про змінні декларації, JavaScript викидає цей аргумент у вікно, змушуючи вас ставити "var" перед новими ідентифікаторами всюди . І тоді він мовчки накрутить вас, якщо ви забудете.
г) прототипи замість класів. Існує дуже мало широкомасштабних додатків реального JavaScript, які не включають власну систему класів, щоб обійти притаманну непотрібність прототипів у великій архітектурі додатків. Ці ж додатки мінімально використовують прототипи для розширення базових типів JavaScript, і лише тому, що JS був настільки погано розроблений, що навіть двом цікавим вбудованим типам, з якими він постачається, не вистачає половини функцій, які ви б їх очікували.
д) Неможливість створення типів прохідних значень. Це є частою проблемою практично у всіх мовах, окрім 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. Я згадав, що вони передані за посиланням?
f) Жоден вбудований модуль не включає і не вимагає функціональності. Серйозно, все-таки. Сторонні бібліотеки існують, але майже всі вони мають якусь помилку чи іншу проблему, що не менш важливо - це заплутана проблема кешування в принаймні Chrome, що робить фактичну розробку болем у задниках.
ж) Динамічне введення тексту. Так, я готовий розпочати цей аргумент. Ви починаєте помічати це найбільше, коли ви припиняєте писати маленькі веб-програми чи веб-сторінки та починаєте писати великі додатки, де у вас є дані, які зберігаються довше, ніж один клік миші або цикл запиту / відповіді: додайте неправильний вид об’єкта до масив обробляти пізніше і отримати збій пізніше від відсутнього методу або члена у зовсім іншому біті коду, ніж де була фактична помилка. Веселі часи. Так, Java робить статичне введення тексту здатися злим. Ні, Java / C # / C ++ - це не єдиний і єдиний спосіб статичного введення тексту. Висновки типу, неявна прив'язка інтерфейсу тощо надають всі переваги "легкого впорядкування та не багато натискань клавіш" на динамічному введенні тексту без усіх помилок. Друга за популярністю веб-мова - ActionScript 3 - насправді набрана статично, незважаючи на те, що інакше ідентична JS / ECMAScript. В сторону я отримую більше збоїв від програм Python на своєму робочому столі Fedora, ніж від програм C / C ++ (насправді жоден із програм C / C ++ на моєму робочому столі не виходить з ладу, тепер, коли я думаю про це). Винятки з відсутніми членами == набагато простіше розробити та підтримувати програми, правда?
h) Швидкість. Так, велика кількість зусиль, які розробляли супер погані дупи, докладають до смішних величезних зусиль, щоб зробити JS майже вдвічі швидшим, ніж низькосортний компілятор C, який один юніор-коледж міг написати за кілька місяців. І LuaJIT знаходиться в тому ж плавні, що і JS, з точки зору основних мовних обмежень, але вдається зробити це краще, ніж будь-яка реалізація JavaScript у будь-якому випадку. Люди, які не розуміють, що насправді роблять усі оптимізації JS у V8 чи подібнихяк стверджувати, що JS може робити дивовижні речі швидкісно, але реальність полягає в тому, що всі ці оптимізації в основному просто "спробуйте дуже дуже важко проаналізувати код, щоб з'ясувати типи змінних, а потім компілюйте його як трохи відсталий статично набраний компілятор мови зробив би це ". О, і трасування є, але потім трасування також працює на статично введених мовах (і працює краще через відсутність потреби в захисних колах типу в створеному машинному коді). Насправді, жодна з цих оптимізацій візбанга не була придумана компанією JS або для неї; більшість взяли з дослідницьких JVM (Java - це зло!) або класичних мов OOP (прототипи приголомшливі!).
i) Навіть IntelliSense не можливий. Хочете побачити, які методи існують для тієї змінної, яку ви отримали там у рядку 187 foo.js у своєму текстовому редакторі? Дуже погано. Простежте через код, поки не з'ясуєте, де він був ініціалізований, а потім пройдіть через код, щоб дізнатися, що його прототип має. І тоді сподіваємось, що код не динамічно змінює прототип за вашою спиною. Насправді, просто запустіть його у веб-переглядачі та встановіть точки перерви, тому що дізнатись нічого корисного про значення будь-яким іншим способом в принципі неможливо для будь-якої бази даних коду, більшої ніж сайти toy_web_app.html, які JavaScript-апологісти використовують для прославлення простоти та простоти JavaScript. Деякі редактори коду дуже важко намагаються зробити краще, і майже начебто вдаються до справді простих випадків, іноді, один раз.
j) Немає переваги. JavaScript навіть не особливий порівняно з іншими динамічно набраними мовами. Він не здатний взагалі нічого цікавого зробити, що також не можуть зробити Lua, Python, Ruby тощо. Жодна реалізація JS не швидша, ніж LuaJIT або PyPy, або різні інші вдосконалені JIT-ing реалізації інших динамічних мови. JS не має до нього плюсів порівняно з іншими загальнодоступними мовами. Ох, хіба що він працює у веб-браузері без плагіна. Яка єдина в світі причина, чому вона така популярна. Насправді, це єдина причина , чому ця подія існує. Якщо хтось 10 років тому щойно подумав: "чорт, давай кинемо в наш веб-переглядач існуючу добре розроблену та налагоджену мову, і змусимо інших хлопців зробити те саме, а не змушувати всіх використовувати цей густий маленький хак-жоб, який NetScape придумав , "Інтернет виглядав би набагато інакше (краще) сьогодні. Уявіть собі майбутнє, якби Chrome кинув Python на Chrome як підтримувану мову. Або, власне, уявіть собі це: Google вводить C / C ++ у Chrome як підтримувану мову (http://code.google.com/p/nativeclient/).