Перейти к основному содержимому
Блокчейн32ГЛАВА 32История JavaScript и TypeScript2015

История JavaScript и TypeScript

Прочитано0%
Квизы0/5
Тренажёрыне пройден0/1
Уровень 1 · Новичок

Зачем это нужно​

История языка — не музейная экскурсия. Это объяснение, почему код ведёт себя странно.

Вот пять фактов, каждый из которых сегодня отнимает у новичка час:

console.log(typeof null); // 'object'
console.log([] == false); // true
console.log(0.1 + 0.2); // 0.30000000000000004
console.log([10, 1, 2].sort()); // [ 1, 10, 2 ]
console.log(typeof NaN); // 'number'

Всё это — живой запуск на Node.js 24, самой свежей версии. Ни один из этих ответов не является «правильным» в человеческом смысле. Каждый — след конкретного решения, принятого в конкретный год конкретным человеком, у которого не было времени подумать.

Понимая историю, вы:

  • перестаёте искать логику там, где её нет, и просто помните исключение;
  • понимаете, почему в интернете половина примеров написана совсем не так, как учат сейчас;
  • знаете, что можно использовать, а что нельзя, — и не по чужому совету, а сами;
  • отличаете «язык такой» от «я что-то делаю не так».

Последнее особенно важно на первом курсе. Половина мучений начинающего — это попытка найти смысл там, где на самом деле лежит совместимость с браузером 1997 года.

Десять дней в мае 1995-го​

Компания Netscape делала браузер Navigator и в 1995 году занимала почти весь рынок. Страницы тогда были полностью мёртвыми: текст, картинки, ссылки. Netscape решил, что странице нужен свой язык — чтобы проверить форму до отправки на сервер и показать что-нибудь в ответ на клик.

Задачу поручили Брендану Айку, который пришёл в компанию в апреле. Условия были такие:

  • язык должен появиться к следующей бете браузера, то есть примерно за две недели;
  • он должен «выглядеть как Java», потому что Java в 1995 году была на пике моды;
  • он должен быть простым настолько, чтобы на нём писали дизайнеры, а не программисты.

Первая работающая версия была написана за десять дней. Это не легенда и не преувеличение — это официальная часть истории языка, о которой сам Айк рассказывал многократно.

Что попало в язык из этих десяти дней:

Откуда взятоЧто именно
Schemeфункции как обычные значения, замыкания
Selfпрототипы вместо классов
Javaвнешний вид: фигурные скобки, for, if, точка с запятой
Спешкаtypeof null, автоматическое приведение типов, var

Первое имя языка было Mocha, второе — LiveScript, и под этим именем он вышел в сентябре 1995-го.

ТРИДЦАТЬ ЛЕТ ОДНОГО ЯЗЫКА1995язык за 10 дней2008движок V82009Node.js2012TypeScript2015ES6 — перелом2026ежегодномежду 1999 и 2009 стандарт не менялся почти десять летвсё, что появилось до 2015, приходится тащить дальше ради совместимости
Тридцать лет одной лентой. Между 1999 и 2009 годом в стандарте не менялось почти ничего — и именно этот застой объясняет, почему всё интересное случилось разом в 2015-м.

Почему «JavaScript», если это не Java​

В декабре 1995 года Netscape и Sun Microsystems выпустили совместное заявление, и LiveScript был переименован в JavaScript.

Причина была чисто маркетинговая. Java принадлежала Sun и переживала бум; Netscape договорился с Sun о партнёрстве, и общее имя должно было помочь обоим. Технического родства между языками нет и не было: у них разная модель типов, разная модель объектов, разная модель памяти и разная область применения.

Знаменитая формулировка, которая полностью описывает ситуацию: Java и JavaScript соотносятся примерно как «автомобиль» и «ковёр» — общее слово в названии есть, общего смысла нет.

Последствия этого решения тянутся до сих пор:

  • вакансии до сих пор путают, а начинающие ищут «уроки Java», попадая не туда;
  • имя JavaScript оставалось торговой маркой Sun (позже Oracle), из-за чего стандарт назвали иначе — об этом ниже;
  • и до сих пор приходится объяснять на каждом собеседовании, что это разные языки.
Интересный факт

В коде на JavaScript действительно встречаются слова из Java, которые ничего не делают: class, extends, super, import, enum, char, int, byte, goto и ещё десяток. Часть из них зарезервировали «на будущее» в 1995 году просто потому, что они были в Java.

Некоторые так и не пригодились: int, char, byte, goto в языке нет и не будет, но использовать их как имена переменных нельзя до сих пор. Попробуйте написать const int = 5 в строгом режиме — получите синтаксическую ошибку из-за решения тридцатилетней давности.

Война браузеров и рождение стандарта​

Успех JavaScript в Navigator означал, что Microsoft обязана ответить. Ответ появился в 1996 году вместе с Internet Explorer 3: язык JScript — восстановленная по поведению копия JavaScript, потому что никакой спецификации не существовало.

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

// код 1998 года: догадаться, где мы находимся
if (document.all) {
// Internet Explorer
} else if (document.layers) {
// Netscape Navigator
}

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

В ноябре 1996 года Netscape передал язык в организацию по стандартизации Ecma International. Идея была простая: пусть будет один документ, по которому все делают одинаково.

ECMAScript: почему у языка два имени​

Первая редакция стандарта — ECMA-262, июнь 1997 года. Языку в стандарте дали имя ECMAScript, и причина этому чисто юридическая: имя JavaScript было торговой маркой Sun, и назвать так открытый стандарт было нельзя.

Так и живём с тех пор:

  • ECMAScript — название стандарта, документа;
  • JavaScript — название языка в обиходе и в вакансиях;
  • ES6, ES2015, ES2020 — версии стандарта.

Сам Брендан Айк называл имя «ECMAScript» неудачным, сравнивая его с кожным заболеванием. Тем не менее прижилось.

Ранние редакции:

ВерсияГодЧто дала
ES11997первая запись того, что уже работало
ES21998только приведение к международному стандарту ISO, без изменений языка
ES31999регулярные выражения, try/catch, do..while, строгое сравнение

ES3 оказалась опорной точкой на целое десятилетие: до 2009 года ничего нового в стандарте не появлялось.

ES4: версия, которой не было​

С 2000 года комитет работал над четвёртой редакцией, и замысел был огромный: классы, модули, пространства имён и статическая типизация прямо в языке. По сути — то, чем позже стал TypeScript, но встроенное.

Проект не вышел. К 2008 году комитет раскололся: одна часть участников считала, что язык нужно менять радикально, другая — что такой скачок сломает существующие сайты и никто не станет его внедрять. Договориться не удалось, и работу закрыли.

Последствия оказались долгими:

  • номер 4 пропущен: после ES3 идёт ES5, версии ES4 в природе не существует;
  • восемь лет застоя: 1999–2009 в языке не менялось ничего;
  • урок комитету: с тех пор изменения принимают маленькими порциями и по одной штуке, а не пакетом;
  • типы в язык так и не попали — и именно этот вакуум через четыре года заняла отдельная надстройка.

ES5 вышла в декабре 2009 года и была сознательно скромной: строгий режим 'use strict', встроенный объект JSON, Object.defineProperty и методы массивов, без которых сегодня не пишут ни строки, — map, filter, reduce, forEach.

ВЕРСИИ СТАНДАРТА: ГДЕ ПРОХОДИТ ГРАНИЦАES31999основа языкаES4не вышелспор убил версиюES52009strict mode, JSONES62015let, class, стрелкиграница «старого» и «нового» кодапосле 2015 версии выходят раз в год и называются по году: ES2016, ES2017, …учить «по версиям» не нужно — нужно знать, что до ES6 писали иначеименно поэтому в старых примерах из интернета сплошной var
Четыре версии стандарта и граница между «старым» и «новым» кодом. Всё, что вы видите в примерах со словом var, написано до этой границы.
Отвечено вопросов: 0 из 5
Сколько времени заняла первая работающая версия JavaScript?
Почему язык назвали JavaScript?
Почему стандарт называется ECMAScript, а не JavaScript?
Что случилось с четвёртой редакцией стандарта?
Что дала ES5 в 2009 году?
Отвечено верно: 0 из 5

2008: V8 и почему JavaScript вдруг стал быстрым​

До 2008 года JavaScript был медленным, и это считалось свойством языка. Программу разбирали и выполняли по строчке — примерно так же, как работает простой интерпретатор.

В сентябре 2008 года Google выпустил браузер Chrome, а вместе с ним движок V8. Главная идея V8 — не интерпретировать, а компилировать код в машинные инструкции прямо во время работы. Этот приём называют JIT-компиляцией: движок смотрит, какие функции вызываются часто, и переводит именно их в машинный код, попутно догадываясь о типах по фактическим значениям.

Разница в скорости оказалась не в проценты, а в десятки раз. Остальные движки ответили тем же в течение года.

Почему это ключевое событие в истории языка: до V8 писать на JavaScript что-то серьёзнее проверки формы было бессмысленно. После V8 стало возможно всё остальное — и первым же следствием стало то, что язык вышел за пределы браузера.

Важно

У JIT-компиляции есть обратная сторона, о которой полезно знать заранее: движок ускоряет код, пока тот предсказуем. Если функция всегда получала числа, а потом ей передали строку, движок выбрасывает оптимизированную версию и начинает заново.

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

2009: Node.js — язык вышел из браузера​

В 2009 году Райан Дал взял движок V8, добавил к нему доступ к файлам, сети и процессам и получил Node.js — способ запускать JavaScript вне браузера.

Что это изменило:

  • один язык стал годиться и для страницы, и для сервера;
  • появились инструменты командной строки на JavaScript — сборщики, линтеры, генераторы;
  • у языка появилась стандартная библиотека, которой у него никогда не было: fs для файлов, http для сети, process для окружения.

Вторая идея Node.js важнее первой. Дал строил его вокруг неблокирующего ввода-вывода: пока запрос к диску или к сети выполняется, поток не ждёт, а занимается другими задачами. Для сервера, обслуживающего тысячи одновременных соединений, это оказалось выигрышной моделью — и вся асинхронность JavaScript, которую сегодня записывают через async/await, выросла именно отсюда.

Для нашего курса Node.js — это то, в чём запускается весь код блокчейн-трека: SDK, скрипты, тесты.

ОДИН ЯЗЫК — РАЗНЫЕ СРЕДЫ ЗАПУСКАсам язык: синтаксис, типы, классыбраузер1995document, fetchNode.js2009fs, http, processDeno2020права на файлыBun2022скорость, всё в одномразница не в языке, а в том, что среда даёт сверх него: файлы, сеть, окно браузера
Сам язык у всех сред одинаковый. Отличаются только возможности, которые среда даёт сверх него: браузер — окно и документ, Node.js — файлы и сеть.

npm и история с одиннадцатью строками​

Вместе с Node.js в 2010 году появился npm — хранилище пакетов и программа для их установки. Идея очевидная: не писать в сотый раз то, что уже написано.

npm вырос в самое большое хранилище кода в мире. И вместе с размером пришла проблема, которую лучше всего описывает один случай.

В марте 2016 года автор пакета left-pad поссорился с площадкой и удалил свой пакет. Пакет состоял из одиннадцати строк и добавлял пробелы в начало строки до нужной длины. В тот же час перестали собираться тысячи проектов по всему миру, включая React и Babel: left-pad оказался зависимостью зависимости зависимости.

Выводы, которые из этого сделала индустрия и которые касаются вас с первого же проекта:

  • каждая зависимость — это доверие: вы пускаете чужой код в свою программу, и код автора зависимости вашей зависимости тоже;
  • держите файл package-lock.json в репозитории — он фиксирует точные версии всего дерева;
  • не ставьте пакет ради одной функции, которую можно написать за пять минут;
  • смотрите на дату последнего обновления и число сопровождающих до установки, а не после.

Особенно это важно в блокчейне: пакет, попавший в проект, работает рядом с приватными ключами.

Отвечено вопросов: 0 из 4
Что принципиально нового сделал движок V8 в 2008 году?
Что такое Node.js?
Чему научил случай с пакетом left-pad?
Зачем держать package-lock.json в репозитории?
Отвечено верно: 0 из 4

2015: ES6 — та самая граница​

В июне 2015 года вышла ES6, она же ES2015. Это самая большая версия за всю историю языка и настоящая граница между старым и новым кодом.

Что появилось разом:

ПоявилосьЧто заменило
let и constvar со всеми его странностями
стрелочные функцииfunction плюс ручное сохранение this
classручную работу с прототипами
модули import/exportподключение файлов тегами и глобальные переменные
шаблонные строкисклейку через +
деструктуризациядесять строк присваиваний
Promiseвложенные коллбэки
Map, Setобъект и массив в неподходящей роли
значения по умолчанию, ...проверки arguments руками

Практический смысл этой даты для вас конкретный: любой пример из интернета, где встречается var, написан до 2015 года. Он не обязательно неправильный, но точно устаревший, и рядом с ним наверняка есть другие устаревшие приёмы.

Вот наглядное подтверждение того, что заменили let и const:

var x = 1;
{ var x = 2; }
console.log(x); // 2 — блок ничего не ограничил

let y = 1;
{ let y = 2; }
console.log(y); // 1 — блок работает как ожидается

Живой запуск даёт 2 и 1. var не видит фигурных скобок, и это была причина огромного числа ошибок до 2015 года.

Что было после: версии по годам​

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

ВерсияЗаметное
ES2016оператор **, метод includes
ES2017async/await — асинхронный код стал похож на обычный
ES2018... для объектов, асинхронный for await
ES2019flat, trimStart, catch без параметра
ES2020?., ??, BigInt — большие целые числа
ES2021replaceAll, логические присваивания
ES2022поля класса с #, at(), await на верхнем уровне модуля
ES2023 и дальшеметоды массивов без изменения оригинала: toSorted, toReversed

Учить это по годам не нужно и вредно. Полезно другое: помнить, что язык продолжает меняться, и любой ответ на форуме, помеченный 2016 годом, может оказаться описанием приёма, который давно заменён встроенной возможностью.

Хороший пример — ?. и ?? из ES2020. До них безопасное чтение вложенного поля выглядело так:

var address = tx && tx.recipient && tx.recipient.address ? tx.recipient.address : 'нет';

А теперь так:

const address = tx?.recipient?.address ?? 'нет';

Одна строка вместо одной длинной и хрупкой. Именно поэтому старые примеры выглядят тяжело.

Как принимают новое: TC39 и стадии​

За развитие языка отвечает комитет TC39 внутри Ecma. В нём представлены компании, которые делают браузеры и движки: Google, Apple, Mozilla, Microsoft и другие, плюс независимые участники.

Любое изменение проходит пять стадий:

СтадияЧто означает
0идея записана
1задача признана осмысленной, ищут решение
2есть черновик синтаксиса
3описание готово, ждут реализации в движках и отзывов
4принято, входит в ближайшую версию стандарта

Практический смысл этой таблицы: увидев в статье «новую возможность JavaScript», первым делом посмотрите стадию. Всё, что ниже 3, может измениться или исчезнуть, и строить на этом проект не стоит.

Главный принцип, которым комитет руководствуется во всех спорах, звучит так: не ломать веб. Страница, написанная в 1998 году, обязана открываться в браузере 2026 года. Отсюда следует всё, что в языке кажется нелогичным, — этому посвящён отдельный раздел ниже.

Отвечено вопросов: 0 из 4
Что означает var в примере из интернета?
Как называются версии стандарта после 2015 года?
В статье описана «новая возможность JavaScript» на стадии 2. Что это значит?
Какой главный принцип TC39?
Отвечено верно: 0 из 4

2012: зачем понадобился TypeScript​

К началу 2010-х выяснилось неприятное: на JavaScript начали писать большие программы, а язык к этому не был приспособлен.

Конкретные боли, из которых вырос TypeScript:

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

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

Именно это решение и обеспечило успех там, где провалились предшественники: переходить можно было по одному файлу, а не переписывать проект целиком.

Ключевые версии:

ВерсияГодЧто дала
0.82012первая публичная
1.02014признание стабильной
2.02016strictNullChecks — переломная возможность
5.x2023стандартные декораторы, ускорение
6.xк 2026версия, которая стоит в этом курсе

Андерс Хейлсберг: один человек и четыре языка​

У TypeScript есть главный архитектор — Андерс Хейлсберг. Его биография объясняет, почему язык получился именно таким.

ГодыЧто сделал
1980-еTurbo Pascal — компилятор, который компилировал быстрее, чем конкуренты успевали запуститься
1990-еDelphi — среда, на которой написана огромная часть корпоративного софта
2000-еC# — главный язык платформы .NET
2012 и далееTypeScript

Через все четыре проекта проходит одна и та же идея: инструмент должен помогать во время написания кода, а не после. Turbo Pascal был известен мгновенной компиляцией, Delphi — подсказками в редакторе, C# — строгостью, которая ловит ошибки заранее.

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

Кстати, из этой же биографии становится понятно, почему записи в TypeScript так похожи на C#: public readonly, private, interface, implements, abstract — почти дословно.

2016: strictNullChecks — переломная версия​

Первые версии TypeScript ловили далеко не всё. Главная дыра была в том, что null и undefined подходили под любой тип: строка могла оказаться null, число — undefined, и компилятор не возражал.

А это ровно та ошибка, которая чаще всего валит настоящие программы:

TypeError: Cannot read properties of undefined (reading 'address')

В TypeScript 2.0 появился флаг strictNullChecks. С ним string означает именно строку, а «строка или ничего» приходится писать явно — string | null, — и компилятор требует проверку перед использованием.

function show(name: string | null) {
console.log(name.length); // ошибка: name может быть null
if (name) console.log(name.length); // а так можно
}

Именно с этой версии TypeScript начали воспринимать всерьёз: он стал ловить ту самую ошибку, ради которой всё затевалось. Сегодня strictNullChecks входит в общий флаг strict, и проект без него считается настроенным небрежно.

Автор идеи «типа, который может быть пустым» — Тони Хоар, придумавший null ещё в 1965 году, — назвал своё изобретение ошибкой на миллиард долларов. strictNullChecks — это способ жить с последствиями.

Где TypeScript заканчивается: типы стираются​

Самое важное, что нужно понять про TypeScript, — где проходит граница его действия.

Возьмём файл с типами и посмотрим, во что его превращает компилятор. Это настоящий вывод tsc --target es2022:

interface Signer { sign(d: string): string; }
type Level = 'low' | 'high';
class Tx implements Signer {
static count = 0;
#secret = 'k';
constructor(public readonly id: string, private amount: number) { Tx.count++; }
get fee(): number { return this.amount * 0.001; }
sign(d: string): string { return d + this.#secret; }
}
const lvl: Level = 'low';

Результат:

"use strict";
class Tx {
id;
amount;
static count = 0;
#secret = 'k';
constructor(id, amount) {
this.id = id;
this.amount = amount;
Tx.count++;
}
get fee() { return this.amount * 0.001; }
sign(d) { return d + this.#secret; }
}
const lvl = 'low';

interface, type, implements, public, readonly, private, все аннотации типов — исчезли полностью. class, static, #secret — остались, потому что это возможности самого JavaScript.

ПОЧЕМУ TYPESCRIPT НИЧЕГО НЕ ПРОВЕРЯЕТ ВО ВРЕМЯ РАБОТЫapp.tsтипы на местеtscпроверил и стёрapp.jsтипов больше нетдвижоквыполняетсюда типы уже не доходятошибка типа ловится на шаге tsc или не ловится вообще — проверять чужие данные всё равно приходится руками
Компилятор проверяет типы и стирает их. К моменту запуска в программе нет ни одного типа — проверять данные, пришедшие извне, всё равно приходится обычным кодом.

Отсюда единственное практическое следствие, которое нужно запомнить накрепко: TypeScript ничего не проверяет во время работы программы. Ответ сервера, содержимое файла, аргументы из командной строки — всё это приходит без типов, и написанный вами type Tx = {...} не остановит мусор. Проверку данных на границе программы пишут руками или библиотекой вроде Zod.

Deno и Bun: попытки переделать Node​

В 2018 году Райан Дал выступил с докладом о том, что он сам считает ошибками в Node.js: доступ к файлам и сети без всякого разрешения, громоздкая система модулей, папка node_modules размером с проект.

Из этого выросли две среды, которые вы наверняка встретите.

Deno (2020, тот же автор): права выдаются явно — без --allow-net программа в сеть не выйдет; TypeScript работает без настройки; стандартная библиотека своя.

Bun (первый выпуск 2022, версия 1.0 в 2023): ставка на скорость. Среда запуска, установщик пакетов, сборщик и запускалка тестов в одной программе; TypeScript тоже из коробки.

Стоит ли переходить: пока нет. Node.js остаётся тем, на чём работает подавляющее большинство проектов, в том числе блокчейн-SDK. Но знать про эти две среды нужно — и потому, что они встречаются в статьях, и потому, что они показывают, куда движется экосистема: разрешения по умолчанию и TypeScript без настройки постепенно перетекают и в Node.js.

Отвечено вопросов: 0 из 5
Почему TypeScript прижился там, где провалились прошлые попытки?
Что даёт флаг strictNullChecks?
Что останется от interface и type после компиляции?
Ответ сервера пришёл с полем amount в виде строки, а в типе указан number. Что сделает TypeScript?
Чем известен Андерс Хейлсберг помимо TypeScript?
Отвечено верно: 0 из 5

Почему в языке столько странного: «не ломать веб»​

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

console.log(typeof null); // 'object'

Ошибка реализации 1995 года: значение null хранилось так, что проверка типа принимала его за объект. Исправить нельзя — тысячи страниц полагаются на текущее поведение. Предложение починить это обсуждалось и было отклонено.

console.log([] == false); // true
console.log('' == 0); // true
console.log(null == undefined); // true
console.log(null == 0); // false

Двойное равенство приводит операнды к общему типу по таблице правил из десяти пунктов. Правила придумывались в спешке и последовательными не получились: null равен undefined, но не равен нулю. Отсюда единственное разумное правило современного кода — всегда ===, а == оставить ровно для одной проверки: x == null ловит сразу null и undefined.

console.log([10, 1, 2].sort()); // [ 1, 10, 2 ]

sort без аргумента сравнивает элементы как строки. Решение 1995 года, менять нельзя.

console.log(typeof NaN); // 'number'
console.log(NaN === NaN); // false

«Не число» имеет тип «число», и оно не равно самому себе. Первое — следствие того, что NaN живёт внутри стандарта чисел IEEE 754, второе — прямое требование этого стандарта. Проверять нужно через Number.isNaN.

const f = () => {
return
42;
};
console.log(f()); // undefined

Автоматическая вставка точек с запятой: язык дописал ; сразу после return, и 42 стало недостижимым кодом. Живой запуск даёт undefined. Отсюда правило: значение пишут на той же строке, что и return.

console.log(Object.keys({ b: 1, a: 2, 1: 3, 0: 4 })); // [ '0', '1', 'b', 'a' ]

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

Общий вывод простой: язык нельзя чинить, его можно только дополнять. Все «исправления» последних тридцати лет — это новые конструкции рядом со старыми: === рядом с ==, let рядом с var, Number.isNaN рядом с isNaN, ?. рядом с ручными проверками. Старое остаётся навсегда, и знать его придётся хотя бы для чтения чужого кода.

Почему в блокчейне именно JavaScript и TypeScript​

Вопрос законный: в блокчейне есть Rust, Go, Solidity, Ride. Откуда там JavaScript?

Ответ в разделении ролей. Языки вроде Solidity и Ride пишут то, что выполняется внутри блокчейна, — смарт-контракты. Всё остальное живёт снаружи, и там почти всегда JavaScript или TypeScript:

  • клиентские библиотеки: SDK Waves Enterprise, ethers.js, web3.js, viem — все на TypeScript;
  • интерфейсы: кошельки, обозреватели блоков, панели — это веб, а веб — это JavaScript;
  • инструменты разработчика: Hardhat, Truffle — на Node.js;
  • скрипты и автоматизация: выпустить токен, разослать транзакции, собрать статистику по блокам.

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

Что дальше: типы в самом JavaScript​

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

// как это выглядело бы
function fee(amount: number): number {
return amount * 0.001;
}

Движок пропустит : number мимо, а TypeScript, как и раньше, проверит. Выигрыш — исчезает шаг сборки: файл с типами можно запускать напрямую.

Предложение находится на ранней стадии, и попадёт ли оно в стандарт — неизвестно. Но направление видно и без него: Node.js уже умеет запускать файлы TypeScript, просто отбрасывая типы, а Deno и Bun делали это с самого начала. Похоже, что через несколько лет отдельный шаг компиляции для простых проектов исчезнет.

Второе заметное направление — скорость самого компилятора. Microsoft объявила о переписывании tsc на языке Go ради многократного ускорения проверки больших проектов; исходный компилятор написан на самом TypeScript, и на проектах в миллион строк это стало заметно.

Типичные заблуждения​

ЗаблуждениеКак на самом деле
«JavaScript — упрощённая Java»Разные языки, общее только слово в названии, и то по маркетинговой договорённости 1995 года
«TypeScript — отдельный язык, надо учить заново»Надстройка: любой корректный файл на JavaScript уже корректен на TypeScript
«TypeScript проверяет данные во время работы»Все типы стираются при компиляции; данные с границы проверяют кодом
«ES6 — это версия JavaScript, а ES2015 — другая»Одно и то же: ES6 — старое название, ES2015 — по году
«Раз есть ES2024, надо учить все версии»Учат язык, а не версии; помнить нужно только границу 2015 года
«var запрещён»Не запрещён и работает до сих пор; просто ведёт себя иначе и в новом коде не нужен
«Node.js — это язык»Это среда запуска: движок V8 плюс доступ к файлам, сети и процессам
«npm-пакет — это безопасно»Это чужой код в вашей программе, и код его зависимостей тоже; left-pad показал цену
«Странности языка когда-нибудь исправят»Не исправят: принцип «не ломать веб» сильнее. Добавят новое рядом со старым

Тренажёр: даты и имена вслепую​

Цель: скорость ≥ 110 зн/мин, точность ≥ 90%

1995 — Брендан Айк, первая версия за десять дней
клавиша ``клавиша 11клавиша 22клавиша 33клавиша 44клавиша 55клавиша 66клавиша 77клавиша 88клавиша 99клавиша 00клавиша --клавиша ==клавиша ⌫⌫клавиша TabTabклавиша QQклавиша WWклавиша EEклавиша RRклавиша TTклавиша YYклавиша UUклавиша IIклавиша OOклавиша PPклавиша [[клавиша ]]клавиша \\клавиша Caps LockCaps Lockклавиша AAклавиша SSклавиша DDклавиша FFклавиша GGклавиша HHклавиша JJклавиша KKклавиша LLклавиша ;;клавиша ''клавиша EnterEnterклавиша ShiftShiftклавиша ZZклавиша XXклавиша CCклавиша VVклавиша BBклавиша NNклавиша MMклавиша ,,клавиша ..клавиша //клавиша ShiftShiftклавиша CtrlCtrlклавиша WinWinклавиша AltAltклавиша ПробелПробелклавиша AltAltклавиша WinWinклавиша MenuMenuклавиша CtrlCtrl
следующая: 1 — мизинец левой руки

Даты, которые стоит помнить​

ГодСобытиеПочему важно
1995Брендан Айк пишет первую версию за десять днейИсточник большинства странностей языка
1995Mocha → LiveScript → JavaScriptИмя дано по маркетинговой договорённости с Sun
1996JScript в Internet Explorer 3Начало войны браузеров и кода в двух вариантах
1997ECMA-262, первая редакцияУ языка появляется стандарт и второе имя
1999ES3Опорная точка на десять лет
2008ES4 закрытНомер 4 пропущен; типы в язык не попали
2008V8 и JIT-компиляцияЯзык стал быстрым, стало возможно всё остальное
2009ES5Строгий режим, JSON, map/filter/reduce
2009Node.jsJavaScript вышел за пределы браузера
2010npmПоявилась экосистема пакетов
2012TypeScript 0.8Типы как надстройка, а не новый язык
2015ES6 / ES2015Граница старого и нового кода
2016strictNullChecksTypeScript начали воспринимать всерьёз
2016случай с left-padУрок про доверие к зависимостям
2017ES2017async/await
2020ES2020, Deno 1.0?. и ??; попытка переделать Node
2022ES2022, первый Bun#-поля класса; ставка на скорость
2026TypeScript 6, ежегодные ESВерсия, стоящая в этом курсе

Что должен уметь​

  • Рассказать, за какой срок и в какой компании появилась первая версия языка и как это отразилось на нём.
  • Объяснить, почему язык называется JavaScript, и опровергнуть родство с Java.
  • Различать имена «JavaScript» и «ECMAScript» и объяснить, откуда взялось второе.
  • Рассказать, что случилось с ES4 и почему после ES3 идёт ES5.
  • Объяснить, что сделал V8 в 2008 году и почему это ключевое событие.
  • Объяснить, что такое Node.js, и не называть его языком.
  • Назвать выводы из случая с left-pad и объяснить, зачем в репозитории package-lock.json.
  • Назвать границу 2015 года и опознавать устаревший пример по слову var.
  • Перечислить, что появилось в ES6, и объяснить, что каждое из этого заменило.
  • Понимать годовую схему версий и не пытаться учить их по номерам.
  • Объяснить, что означают стадии TC39, и определять, можно ли использовать возможность из статьи.
  • Назвать принцип «не ломать веб» и объяснить через него typeof null, ==, sort и вставку точек с запятой.
  • Рассказать, из каких проблем вырос TypeScript и почему он сделан надстройкой.
  • Объяснить, что даёт strictNullChecks и почему эта версия считается переломной.
  • Показать на примере, что от типов не остаётся ничего после компиляции.
  • Объяснить, почему тип не спасает от плохих данных, пришедших по сети.
  • Назвать, чем известен Андерс Хейлсберг, и связать это со сходством TypeScript и C#.
  • Отличать Deno и Bun от Node.js и объяснить, зачем они появились.
  • Объяснить, почему в блокчейне клиентская часть почти всегда на TypeScript.
Углубиться

Почему typeof null даёт 'object'. В первой реализации значение хранилось как пара «метка типа + данные», и метка 000 означала объект. Нулевой указатель состоял из одних нулей, поэтому проверка типа честно видела метку объекта. Предложение исправить это выносилось на комитет и было отклонено: слишком много кода полагается на текущее поведение.

arguments и почему стрелки его не имеют. До ES6 у любой функции был скрытый объект arguments со всеми переданными значениями — так обходились без остаточных параметров. Стрелочные функции его не получили намеренно: у них нет ни своего this, ни arguments, и это делает их предсказуемыми.

Transpilers. С 2013 по 2018 год существовал целый жанр инструментов, переводивших новый JavaScript в старый: Traceur, затем Babel. Без них пользоваться ES6 было нельзя — браузеры не успевали. Сегодня Babel остался в основном ради JSX и совсем старых браузеров, а его роль перешла к более быстрым инструментам вроде esbuild и SWC.

CommonJS против модулей ES. Node.js в 2009 году не мог ждать стандартных модулей и придумал свои — require и module.exports. Стандартные import/export появились в 2015-м и оказались устроены иначе: они разбираются до выполнения файла. Две системы сосуществуют до сих пор, и большая часть настроечной боли в проектах на Node.js растёт именно отсюда.

JavaScript и другие «компилируемые в JS» языки. TypeScript был не первым: были GWT (Java в JS), CoffeeScript, Dart, Elm, ClojureScript, ReasonML. Победил тот, кто не требовал бросать существующий код и не изобретал новый синтаксис ради красоты.

WebAssembly. С 2017 года в браузере можно выполнять двоичный формат, в который компилируют Rust, C++ и Go. Это не замена JavaScript, а дополнение для тяжёлых вычислений: криптографии, обработки изображений, игр. В блокчейн-инструментах WebAssembly встречается регулярно — например, для проверки подписей в браузере.

Дальше по теме:

Сводная проверка по всей главе: 18 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.

Куда дальше: проверенные ресурсы​

Видео по теме

ВидеоA Brief History of JavaScript, talk by Brendan Eich (creator of JavaScript)freeCodeCamp.org
ВидеоИстория языка JavaScriptCodeArmy
ВидеоИстория языка TypeScriptCodeArmy
ВидеоВ чем разница между ECMAScript и JavaScript?Pro Web
ВидеоThe Weird History of JavaScriptFireship

Комментарии

Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.