Отдел фронтенд-разработки компании Лайв Тайпинг перевёл для читателей Хабра большой материал о зарождении, развитии и перспективах языка JavaScript, вышедший в блоге сервиса Auth0. Сегодня мы публикуем первую часть перевода. Соперничество Netscape и Mosaic, грёзы об интерактивном вебе, язык программирования для не-программистов, переход от классов к прототипам и что общего между JavaScript и ECMAScript (спойлер: всё).
JavaScript, вероятно, является одним из самых важных языков программирования на сегодняшний день. Благодаря развитию веба JavaScript достиг высот, которых ему не сулили. В этой статье мы рассмотрим весь путь JavaScript от создания до сегодняшних дней и постараемся заглянуть в его будущее.
Все началось в 90-е
События, в результате которых появился JavaScript, разворачивались в течение шести месяцев, с мая по декабрь 1995 года. Компания Netscape Communications уверенно прокладывала себе путь в области веб-технологий. Её браузер Netscape Communicator успешно отвоевывал позиции у NCSA Mosaic, первого популярного веб-браузера. Netscape была создана людьми, принимавшими участие в разработке Mosaic в ранние 90-е. Теперь, с деньгами и независимостью, у них было всё необходимое для поиска способов дальнейшего развития веб-технологий. Именно это послужило толчком для рождения JavaScript.
Основатель Netscape Communications и бывший участник команды Mosaic Марк Андриссен считал, что веб должен стать более динамичным. Анимации, взаимодействие с пользователями и другие виды интерактивности должны стать неотъемлемой частью интернета будущего. Веб нуждался в лёгком скриптовом языке (или языке сценариев — прим.ред.), способном работать с DOM, который в те дни не был стандартизирован. Существовало одно «но», являвшееся на тот момент серьёзным вызовом: этот язык не должен был предназначаться для крупных разработчиков и прочих людей, имевших отношение к инженерной стороне вопроса. Java в те дни уже активно развивалась и твёрдо заняла эту нишу. Таким образом, новый скриптовый язык должен был предназначаться для совершенно иной аудитории — дизайнеров. Очевидно, что веб был статичным, а HTML был достаточно молод и прост в освоении даже для тех, кто не имел ничего общего с программированием. Следовательно, всё, что должно было стать частью браузера и сделать веб более динамичным, должно быть максимально понятным для далёких от программирования людей. Из этого предположения родилась идея Mocha, который должен был стать тем самым простым, динамичным и доступным скриптовым языком.
И тут в нашей истории появляется Брендан Айк, отец JavaScript. Айк должен был разработать для Netscape «Scheme для браузера». Scheme — это динамичный, мощный и функциональный диалект языка программирования Lisp с максимально упрощённым синтаксисом. Вебу требовалось что-то подобное: простое в освоении, динамичное, немногословное и мощное. Айк не стал упускать шанса поработать над тем, что ему нравилось, и присоединился к команде.
Перед командой была поставлена задача подготовить работающий прототип в кратчайшие сроки. Sun Microsystems заканчивала работу над своим языком программирования Java, на тот момент называвшимся Oak, и Netscape Communications была уже готова заключить с компанией контракт, чтобы сделать Java доступным в своем браузере. Так зачем же понадобился Mocha (первое название JavaScript)? Зачем нужно было создавать абсолютно новый язык программирования при наличии готовой альтернативы? Дело в том, что Java не был предназначен для той аудитории, на которую ориентировался Mocha — скриптеры, любители, дизайнеры. Java был слишком большим и навороченным для того, чтобы выполнять эту роль. Основная идея заключалась в том, что Java должен был предназначаться для крупных разработчиков и профессиональных программистов, в то время, как Mocha должен был использоваться для небольших скриптовых задач. Другими словами, Mocha должен был стать скриптовым компаньоном для Java по принципу, аналогичному тому, как взаимодействуют C/C++ и Visual Basic на платформе Windows.
Инженеры Netscape приступили к детальному изучению Java. Они даже начали разрабатывать собственную виртуальную машину Java, однако проект быстро свернули, так как она не могла достичь идеальной совместимости с виртуальной машиной Sun Microsystems.
Проблема скорейшего выбора языка стояла как никогда остро. Возможными кандидатами были Python, Tcl и Scheme. Айк должен был действовать быстро. По сравнению с конкурентами у него были два преимущества: свобода в определении набора необходимых возможностей и прямая связь с заказчиком. К несчастью, имело место и очевидное неудобство: для принятия огромного количества важных решений времени практически не было. JavaScript, a.k.a. Mocha, был рождён именно в таких условиях. В течение нескольких недель был подготовлен рабочий прототип, который затем был интегрирован в Netscape Communicator.
То, что должно было стать аналогом Scheme для браузера, вылилось в нечто совершенно иное. Рукой Айка управляли необходимость закрыть сделку с Sun и сделать Mocha скриптовым компаньоном для Java. Синтаксис должен был быть максимально близким Java. Помимо этого, от Java была унаследована семантика для большого количества устоявшихся идиом. Таким образом, Mocha был совсем не похож на Scheme. Он выглядел, как динамический Java, под оболочкой которого скрывался гибрид Scheme и Self.
Прототип Mocha был интегрирован в Netscape Communicator в мае 1995 года. Через очень короткий промежуток времени он был переименован в LiveScript, так как в тот момент слово live выглядело очень привлекательным с точки зрения маркетологов. В декабре 1995 года сделка между Netscape Communications была закрыта: Mocha/LiveScript был переименован в JavaScript и преподносился в качестве скриптового языка для выполнения небольших клиентских задач в браузере, в то время, как Java был полноценным профессиональным языком программирования для разработки сложных веб-компонентов.
Первая версия JavaScript заложила все те фундаментальные особенности, которыми этот язык знаменит и поныне. В частности, его объектная модель и функциональные особенности уже присутствовали в первой версии.
Трудно сказать, как развивались бы события, если бы Айк не успел предоставить рабочий прототип вовремя. Python, Tcl, Scheme, рассматривавшиеся в качестве альтернативы, были совершенно не похожи на Java. Sun было бы трудно принять в качестве языка-компаньона для Java варианты, в корне отличавшиеся от него. С другой стороны, Java долгое время был важной частью веба. Если бы Sun не являлись определяющим фактором, у Netscape было бы намного больше свободы в выборе языка. Но стала бы Netscape разрабатывать собственный язык или воспользовалась одним из существующих? Этого мы никогда не узнаем.
Различные реализации
Когда Sun и Netscape закрыли сделку, и Mocha/LiveScript был переименован в JavaScript, встал ребром очень важный вопрос: что будет с конкурентами? Хоть Netscape и набирал популярность, становясь самым используемым браузером, Microsoft занималась активной разработкой Internet Explorer. С самых первых дней JavaScript показал настолько удивительные возможности в плане взаимодействия с пользователем, что соперничающим браузерам не оставалось ничего иного, кроме как в кратчайшие сроки найти готовые решения, представлявшие собой рабочие реализации JavaScript. В тот момент (и ещё достаточно долго после этого) веб-стандарты оставались достаточно слабыми. Поэтому Microsoft разработала свою реализацию JavaScript, назвав ее JScript. Убрав из названия слово Java, они смогли избежать возможных проблем с владельцами торговой марки. Однако, JScript отличался не только названием. Небольшие различия в реализации — в частности, подход к некоторым DOM функциям — оставили рябь, которая будет ощущаться ещё долгие годы. Бои за JavaScript шли на гораздо большем количестве фронтов, чем названия и таймлайны, и многие причуды этого языка появились благодаря им. Первая версия JScript появилась в Internet Explorer 3.0, увидевшем свет в августе 1996 года.
Реализация JavaScript получила свое собственное название и в Netscape. Версия, выпущенная вместе с Netscape Navigator 2.0, была известна, как Mocha. Осенью 1996 года Айк переписал бóльшую часть Mocha, чтобы разобраться с техническими огрехами и недоработками, возникшими, как следствие спешки при разработке. Новая версия была названа SpiderMonkey. Это название используется по сей день в JavaScript-движке браузера Firefox, внука Netscape Navigator.
В течение нескольких лет JScript и SpiderMonkey были единственными движками JavaScript. Особенности обоих движков, не всегда совместимые, определили вектор развития веба на ближайшие годы.
Основные особенности архитектуры
Несмотря на то, что JavaScript был рождён в спешке, некоторые мощные особенности были заложены в нём с самого начала. Эти особенности определяли JavaScript как язык и позволили ему перерасти собственные границы, несмотря на все его причуды.
«Решение использовать готовый язык вместо изобретения своего никаким образом не зависело от меня. Установка, поступившая с самых верхов, звучала так: “Язык должен выглядеть как Java”. Это сразу отбросило Perl, Python и Tcl вместе со Scheme. Позже, в 1996 году, к нам зашёл Джон Оустерхаут, чтобы показать Tk и посокрушаться по поводу упущенной возможности для Tcl. Я не горжусь, но я счастлив, что я выбрал в качестве основных ингредиентов функции первого класса по подобию Scheme и прототипное программирование Self. Влияние Java, особенно баги с датами в 2000 году и чувствительность к регистру, стало досадным недоразумением.» — Brendan Eich's blog: Popularity
Хотя создание синтаксиса, максимально близкого к Java, не было основной идеей JavaScript, рынок внёс свои коррективы. Возможно, для решения определённых задач больше подошёл бы другой синтаксис, однако благодаря использованию всем знакомого синтаксиса JavaScript с лёгкостью набрал популярность.
Сравните этот пример, написанный на Java:
public class Sample {
public static void main(String[] args) {
System.out.println("Hello world!");
try {
final MissileSilo silo = new MissileSilo("silo.weapons.mil");
silo.launchMissile(args[0]);
} catch(Exception e) {
System.out.println("Unexpected exception: " + e);
}
}
}
с этим примером, написанным на JavaScript:
console.log('Hello world');
try {
const silo = new MissileSilo('silo.weapons.mil');
silo.launchMissile(process.argv[0]);
} catch(e) {
console.log('Unexpected exception' + e);
}
Функции как объекты
Функции в JavaScript — это просто ещё один тип объекта. Ими можно оперировать, как и любыми другими элементами. Их можно привязывать к переменным и, в более поздних версиях JavaScript, даже выбрасывать как исключения. Вероятней всего, что этой особенностью JavaScript обязан Scheme.
var myFunction = function() {
console.log('hello');
}
otherFunction(myFunction);
myFunction.property = '1';
Благодаря тому, что функции рассматриваются как объекты, стали возможными различные функциональные паттерны:
var a = [1, 2, 3];
a.forEach(function(e) {
console.log(e);
});
Эти паттерны с успехом используются во множестве библиотек, таких, как underscore и immutable.js.
Прототипное программирование
Хотя прототипное программирование стало популярным благодаря JavaScript, впервые оно была представлено в Self. Айк отдавал предпочтение именно этому стилю программирования, оказавшемуся достаточно мощным, чтобы смоделировать более традиционный подход Simula-подобных языков, таких, как Java или C++. По большому счету, классы, реализованные в современной версии JavaScript, не что иное, как синтаксический сахар, которым посыпана прототипная система.
Создатели Self, языка программирования, вдохновившего Айка на введение прототипов в JavaScript, пытались избежать проблем, связанных с объектами в Simula-подобных языках. В частности, ветвление между классами и экземплярами стало причиной многих проблем, присущих Simula-подобным языкам. Неоднократно обсуждалась проблема, возникавшая, когда код программы развивался и становился больше: так как классы являлись архетипом для всех новых объектов, с ростом кода становилось всё сложнее адаптировать базовые классы под новые требования, возникавшие в процессе. Подобной проблемы можно избежать, делая новые экземпляры прототипов, из которых, в свою очередь, создавались бы новые объекты. Это и есть основная концепция прототипов: образец, которому можно задать его собственные параметры. Если прототип не подходил для нового объекта, его можно было клонировать и модифицировать, не оказывая никакого влияния на другие дочерние экземпляры. В языках, основанных на классах, осуществить такой подход крайне сложно.
function Vehicle(maxSpeed) {
this.maxSpeed = maxSpeed;
}
Vehicle.prototype.maxSpeed = function() {
return this.maxSpeed;
}
function Car(maxSpeed) {
Vehicle.call(this, maxSpeed);
}
Car.prototype = new Vehicle();
Благодаря силе прототипов JavaScript получился на редкость гибким. На волне вдохновения разработчики создали огромное количество библиотек со своими собственными объектными моделями. Популярная библиотека Stampit выжимает из прототипной системы всё возможное для того, чтобы манипулировать объектами так, как это невозможно в традиционных языках, базирующихся на классах.
Прототипы сделали JavaScript обманчиво простым, дав разработчикам библиотек огромную силу.
Большая причуда: примитивы и объекты
Пожалуй, одной из самых больших ошибок, допущенных из-за спешки, в которой разрабатывался JavaScript, стало то, что объекты, ведущие себя совершенно идентично, могут быть различных типов. Например, тип строки (Hello world) не совпадает с типом нового объекта String (new String('Hello world')). Это порой приводит к нежелательным последствиям, которые могут сбить с толку.
> typeof "hello world"
< "string"
> typeof new String('hello world')
< "object"
Но это было только началом в истории JavaScript. Поспешная разработка стала причиной большого количества архитектурных ошибок, которые могли стать настоящим кошмаром. Однако сроки поджимали, и всё пришлось оставить как есть.
«Всё остальное — это извращенная, безжалостная история. JavaScript стал самой популярной клиентской реализацией Java, с которой мог соперничать только Flash, поддерживавший ActionScript — прямого потомка JavaScript.» — Brendan Eich's blog: Popularity
По волнам моей памяти: взгляд на Netscape Navigator 2.0 и 3.0
Первая публичная версия JavaScript была встроена в Netscape Navigator 2.0, выпущенный в 2005 году. Благодаря чудесам виртуализации и устаревшим и неподдерживаемым сайтам мы можем заново пережить эти моменты счастья.
К сожалению, многие базовые функции JavaScript в то время не работали. Анонимные функции и цепочки прототипов, две самые мощные особенности, не работали так, как они работают сегодня. Тем не менее, эти особенности на тот момент уже были спроектированы и должны были воплотиться в жизнь в ближайшие годы. Следует заметить, что данная версия интерпретатора JavaScript считалась альфа-версией.
К огромной радости, годом позже был выпущен Netscape Navigator 3.0, и он очень сильно отличался от своего предшественника:
Обратите внимание, сообщение об ошибке даёт гораздо больше информации о происходящем. Это, в свою очередь, позволяет нам понять, что интерпретатор воспринимает свойство прототипа по-своему. Мы подменяем объект базовым экземпляром Object, слегка модифицируем его, и — вуаля — всё работает! По крайней мере, частично. Судя по всему, присвоение внутри тестовой функции не делает ровным счётом ничего. Вполне очевидно, что впереди будет ещё много работы, и тем не менее, JavaScript в текущем состоянии вполне мог использоваться для большинства задач, и его популярность продолжала расти.
Такие возможности как регулярные выражения, JSON и исключения были ещё недоступны. В последующие годы развитие JavaScript происходило невероятно быстро.
ECMAScript: стандартизированный JavaScript
Первой большой переменой для JavaScript после его выпуска стала стандартизация ECMA. ECMA — ассоциация, созданная в 1961 году с целью стандартизации информационных и коммуникационных систем.
Работа над стандартизацией JavaScript началась в ноябре 1996 года. Стандарту, над которым работала группа TC-39, был присвоен идентификационный номер ECMA-262. К тому моменту JavaScript активно использовался на многих веб-страницах. В этом пресс-релизе 1996 года указано количество в 300000 страниц, использующих JavaScript.
JavaScript и Java лежат в основе Netscape ONE — платформы для разработки интернет- и интранет-приложений. В течение короткого времени с момента своего внедрения в прошлом году новые языки получили признание среди разработчиков, благодаря чему на данный момент существует более 175000 Java-апплетов и более 300000 страниц, использующих JavaScript по всему интернету, согласно www.hotbot.com. — Netscape Press Release
Стандартизация стала для молодого языка не только важным шагом, но и серьезным вызовом. Она открыла JavaScript для большей аудитории и дала возможность сторонним разработчикам принимать участие в развитии языка. Она также помогла держать других разработчиков в рамках. В те времена бытовало опасение, что Microsoft или кто-либо ещё могут слишком сильно отклониться от оригинальной реализации языка, что могло привести к фрагментации.
Из-за проблем с торговой маркой ECMA не могла использовать JavaScript в качестве названия. После непродолжительных дебатов было решено, что описанный стандартом язык программирования будет назван ECMAScript. На сегодняшний день JavaScript это всего-лишь коммерческое название ECMAScript.
Продолжение следует.
Автор: Лайв Тайпинг