Ecmascript 6 — что можно использовать уже сейчас
Примечание: статья расчитана в основном на не-Javascript программистов — иногда я буду вдаваться в объяснения достаточно основных вещей, но надеюсь будет полезна и тем, кто просто не успел ознакомиться с большинством нововведений ES6.
Как известно, стандарт Ecmascript 6 собираются опубликовать в июне 2015. Но так как многое уже имплементировано в современный браузерах, почему-бы не начать использовать это прямо сейчас? Поскольку jsFiddle и аналоги ES6 не поддерживают, буду использовать es6fiddle для примеров. К сожалению, не все в нем можно показать из-за багов. При отсутствии ссылок на es6fiddle рекомендую копировать сниппеты кода в консоль современного браузера и выполнять их — для наглядности. Рекомендую крайний стабильный Firefox (версия 33 на момент написания статьи) — там все работает «из коробки».
Так как изменений очень много, опишу субъективно самые важные.
let и scope — переменные с блочной областью видимости (block scope)Одна из самых раздражающих/непонятных для начинающих JS-программистов вещей это область видимости переменных в JS. Пример: for (var i=0; i<10; i++){ } console.log(i); В большинстве языков подобный код выкинет ошибку что i не дефинирована, но в JS в консоль выведется число «10». Причина в том, что в JS используется hoisting — то есть декларации всех используемых переменных переносятся в начало функции (и соответственно i доступна вне блока for). Именно поэтому советуют декларировать все переменные в начале функции — все равно они будут туда перенесены при выполнении кода.В ES6 можно написать:
for (let j=0; j<10; j++){ } console.log(j); В этом коде область видимости j ограничена блоком for. Больше нет смысла декларировать переменные в начале функции!
Про const говорить особо нечего — это декларация константы, при повторном присвоении значения выбрасывает TypeError (в strict mode).
Пример:
function setConst (){ «use strict»; const xx = 10; xx = 11; console.log (xx); } setConst (); Ссылок на примеры нет, так как на данный момент block scope в es6fiddle не поддерживается. Ждем фиксов.
Arrow functions Если вы использовали лямбды в C#, вы сразу узнаете синтаксис (это не случайность — он был взят именно оттуда).Как писали раньше: function SomeClass () { var self = this; //самый простой способ сохранить контекст нужного объекта self.iter = 0;
setInterval (function () { self.iter++; console.log ('current iteration: ' + self.iter); }, 1000); }
var sc = new SomeClass (); В ES6 можно гораздо проще:
function SomeClass () { this.iter = 0;
setInterval (() => { this.iter++; console.log ('current iteration: ' + this.iter); }, 1000); }
var sc = new SomeClass (); es6fiddleКак видно, arrow function не создает своего контекста, так что this будет указывать на контекст функции, в которой вызван код.
Пример с параметрами:
let numList = [1,2,3]; let doubleNumList = numList.map (n => n*2); console.log (doubleNumList); es6fiddleСравните, насколько более громоздкий старый метод:
let numList = [1,2,3]; let doubleNumList = numList.map (function (n){ return n*2; }); console.log (doubleNumList); Классы Старый способ эмулировать классы в JS выглядит как-то так: function Vehicle (topSpeed){ this.topSpeed = topSpeed; this.printTopSpeed = function (){ console.log ('Top speed:'+this.topSpeed+' km/h'); } }
var myVehicle = new Vehicle (50); myVehicle.printTopSpeed (); jsFiddle«Традиционное» наследование как в Java/C# можно так-же эмулировать через протопипную модель (код приводить не буду, чтобы не раздувать статью).В ES6 появляются «настоящие» классы:
class Vehicle { constructor (topSpeed){ this.topSpeed = topSpeed; } printTopSpeed (){ console.log ('Top speed:'+this.topSpeed+' km/h'); } }
class Bicycle extends Vehicle { constructor (topSpeed, wheelSize, bicycleType, producedBy){ super (topSpeed); this.wheelSize = wheelSize; this.bicycleType = bicycleType; this.producedBy = producedBy; } static wheelCount (){ return 2; } get bikeInfo (){ return this.producedBy + ' ' + this.bicycleType + ' bike'; } printBicycleType (){ console.log ('Type:'+this.bicycleType+' bike'); } }
var myBike = new Bicycle (40,622,'road','Trek');
myBike.printTopSpeed (); myBike.printBicycleType ();
console.log ('Bicycles have '+Bicycle.wheelCount ()+' wheels');
console.log (myBike.bikeInfo); es6fiddleДумаю, что код выше в комментариях не нуждается. Как видно, в классах можно дефинировать геттеры и статические методы (но не поля), синтаксис интуитивно понятен. Стоит отметить, что тело класса (class body) всегда интерпретируется в strict mode. Ну и конечно никто не заставляет оголтелых адептов прототипного наследования менять свои привычки — классы это вообщем-то синтаксический сахар поверх старой модели.
Destructuring assignment Напоследок, небольшая, но интересная фича, которая облегчает присвоение значений. Пример: function getFirstPrimeNumbers (){ return [2,3,5]; }
var [firstPrime, secondPrime, thirdPrime] = getFirstPrimeNumbers ();
console.log (thirdPrime); //5
//обмен значений (value swap) var [x, y] = [1,2]; console.log ('x:'+x, 'y:'+y); //x:1 y:2 [x, y] = [y, x]; console.log ('x:'+x, 'y:'+y); //x:2 y:1 es6fiddleТеперь можно обменивать значения без временной переменной, что сокращает код.
Немного более сложный пример:
var myBook = { title: «Surely You’re Joking, Mr. Feynman!», author:{ firstName: 'Richard', lastName: 'Feynman', yearBorn: 1918 } };
function getTitleAndAuthorsLastName ({ title, author: { lastName } }){ return 'title: '+ title + ' last name:'+lastName; }
console.log (getTitleAndAuthorsLastName (myBook)); es6fiddleКак использовать? Предвижу возмущение — как видно из все той-же таблицы, кое-где ES6 сразу не работает. Хром, к примеру, не поддерживает большинство вещей из списка, если не включен флаг Enable Experimental JavaScript. Выход — использовать Traceur, компилятор из ES 6 в ES 5.Именно он используется в es6fiddle, кстати. На странице в гитхабе есть инструкция по использованию. Вкратце для браузера:1. Подключаем 2 JS файла:
2. Добавляем для поддержки эксперементальных фич ES6: 3. Пишем код в script тегах с типом module: Заключение Надеюсь, что данная статья смогла показать, что Javascript на данный момент развился в достаточно серьезный язык программирования (хоть и с местами странным поведением). Это не значит что надо выкидывать любимые Java/C#/C++ на помойку, это значит что овладеть джаваскриптом стало еще легче, за счет удобного синтаксиса и более стабильного поведения.