Ecmascript 6 - що можна використовувати вже зараз



Примітка: стаття розрахована в основному на не-Javascript програмістів — іноді я буду вдаватися в пояснення досить основних речей, але, сподіваюся, буде корисна і тим, хто просто не встиг ознайомитися з більшістю нововведень ES6.

Як відомо, стандарт Ecmascript 6 збираються опублікувати в червні 2015. Але так як багато вже імплементовано в сучасний браузерах, чому-б не почати використовувати це прямо зараз?
Оскільки jsFiddle і аналоги ES6 не підтримують, буду використовувати es6fiddle для прикладів. На жаль, не все в ньому можна показати через багів. При відсутності посилань на es6fiddle рекомендую копіювати фрагменти коду в консоль сучасного браузера і виконувати їх — для наочності. Рекомендую крайній стабільний Firefox (версія 33 на момент написання статті) — там все працює «з коробки».



Так як змін дуже багато, опишу суб'єктивно найважливіші.

let та scope — змінні з блочною областю видимості (block scope)

Одна з найбільш дратівливих/незрозумілих для початківців JS-програмістів речей це область видимості змінних в PHP. Приклад:
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 не створює свого контексту, так що це буде вказувати на контекст функції, в якій викликаний код.

Приклад з параметрами:
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 Жартував, 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 файлу:
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script> 

2. Додаємо для підтримки експериментальних фіч ES6:
<script>
traceur.options.experimental = true;
</script>

3. Пишемо код script тегах з типом module:
<script type="module">
нехай a = 10;
</script>


Висновок

Сподіваюся, що дана стаття змогла показати, що Javascript на даний момент розвинувся в досить серйозний мова програмування (хоч і з місцями дивною поведінкою). Це не означає що треба викидати улюблені Java/C#/C++ на смітник, це означає що оволодіти джаваскриптом стало ще легше, за рахунок зручного синтаксису і більш стабільного поведінки.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.