...

воскресенье, 9 ноября 2014 г.

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++ на помойку, это значит что овладеть джаваскриптом стало еще легче, за счет удобного синтаксиса и более стабильного поведения.

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий