ECMAScript 6 — что нового
Table of Contents
Содержание
- let
- const
- Блочные функции
- Выражение деструктурирования
- Значения по умолчанию для аргументов функций
- Остальные параметры вызова функции
- Spread
- Proxy
- WeakMap
- Итераторы
- Генераторы
- Comprehensions
- for…of
- StructType
- Классы (class)
- Модули
- Строки-шаблоны
- Полезные ссылки
let
объявление переменной (аналог var), локальной для блока (внутри if, switch и т.п.).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var a = 5; var b = 10; if (a === 5) { let a = 4; // видна только внутри if var b = 1; // видна везде внутри функции console.log(a); // 4 console.log(b); // 1 } console.log(a); // 5 console.log(b); // 1 |
Ссылки:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/let,
http://wiki.ecmascript.org/doku.php?id=harmony:let
const
объявляет переменную и присваивает ей значение, которое потом не может быть изменено.
1 2 3 4 5 6 7 8 9 |
const a = 15; console.log(a); // 15 a = 1; console.log(a); // 15 const b; console.log(b); // undefined b = 1; console.log(b); // undefined |
Ссылки:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/const,
http://wiki.ecmascript.org/doku.php?id=harmony:const
Блочные функции
функции, видимые только внутри блока (по аналогии с let).
1 2 3 4 5 |
// обычная функция [1, 2, 3].map(function (x) { return x // блочная функция [1, 2, 3].map {|x| x * x} // [1, 4, 9] |
http://wiki.ecmascript.org/doku.php?id=harmony:block_functions,
http://www.slideshare.net/dmitrysoshnikov/falsyvalues-dmitry-soshnikov-ecmascript-6
Выражение деструктурирования
«Разворачивает» объект или массив в последовательность переменных. При этом при разворачивании объекта нужно указать только ключи, которые нужны.
Аналоги: в Python это называется распаковыванием, в php для этого используется функция list.
1 2 3 4 5 6 7 8 9 10 |
var a, b, c = [1, 2]; [a, b] = c; console.log(a, b); // 1, 2 var pt = {x:2, y:-5, z: 1}; var {x, y1, z} = pt; console.log(x, y1, z); // 2, undefined, 1 console.log(y); // ReferenceError: y is not defined var {x: n1, y1: n2, z: n3} = pt; console.log(n1, n2, n3); // 2, undefined, 1 |
Значения по умолчанию для аргументов функций
1 2 3 4 5 |
function multiply(a, b = 1) { return a*b; } multiply(5); // 5 |
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/default_parameters
Остальные параметры вызова функции
Конструкция позволяет получить все параметры вызова функции, для которых не определены аргументы, в виде массива (замена arguments)
1 2 3 4 5 6 7 |
function fun1(a, b, ...theArgs) { console.log(theArgs.length); } fun1(); // 0 fun1(5); // 0 fun1(5, 6, 7); // 1 |
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/rest_parameters
Spread
Распаковывание массива в параметры вызова функции (аналог распаковки кортежа в параметры вызова функции в Python)
1 |
let a = [0,1,2,3], o = func(...a); |
https://developer.mozilla.org/en-US/docs/Syntax/Spread_operator (на момент написания ссылка ведёт на пустую статью).
Proxy
Кто-то называет это мета-объектами, но, к сожалению, очень это похоже на классы. Лично я надеюсь, что широкого распространения эта функциональность не получит. (Возможно тоже вдохновлено Python-овскими метаклассами, но всё-таки мета-объекты — это же классы).
В примере заменяется метод get объекта, чтобы для несуществующего свойства возвращать 37, а не undefined:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var handler = { get: function(target, name){ return name in target? target[name] : 37; } } var p = new Proxy({}, handler); p.a = 1; p.b = undefined; console.log(p.a, p.b); // 1, undefined console.log('c' in p, p.c); // false, 37 |
Подробнее: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Proxy,
http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api.
WeakMap
Объект, ключами которого могут быть объекты. Вроде как не боится циклических ссылок внутри себя.
Имеет методы get, set, has, delete.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var wm1 = new WeakMap(), wm2 = new WeakMap(); var o1 = {}, o2 = function(){}, o3 = window; wm1.set(o1, 37); wm1.set(o2, "azerty"); wm2.set(o1, o2); // любое значение, включая функции и объекты wm2.set(o3, undefined); wm2.set(wm1, wm2); // ключами и значениями могут быть любые объекты, даже WeakMaps wm1.get(o2); // "azerty" wm2.get(o2); // undefined, т.к. нет такого ключа wm2.get(o3); // undefined, т.к. там хранится именно это значение wm1.has(o2); // true wm2.has(o2); // false wm2.has(o3); // true (несмотря на значение "undefined") wm1.has(o1); // true wm1.delete(o1); wm1.has(o1); // false |
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/WeakMap
Итераторы
Объект, который знает, в каком порядке нужно обходить его свойства, и хранит текущую позицию в обходе. Сводится к методу next.
1 2 3 4 5 6 7 8 9 10 |
var lang = { name: 'JavaScript', birthYear: 1995 }; var it = Iterator(lang); // однажды инициализированный, позволяет получить последовательный доступ к парам ключ-значение объекта var pair = it.next(); // пара ["name", "JavaScript"] pair = it.next(); // пара ["birthYear", 1995] pair = it.next(); // Возбуждается исключение StopIteration // удобно использовать для обхода объекта var it = Iterator(lang); for (var pair in it) console.log(pair); // каждый раз выводит пару [key, value] |
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Iterators_and_Generators.
Частные случаи итераторов — генераторы и прокси-объекты (могут быть).
Генераторы
Упрощённые итераторы. Отличаются от обычных функций тем, что не вычисляют все значения сразу (если, допустим, в результате получается массив), а вычисляет следующее значение после обращения к нему. Это позволяет сберечь память и делать вычисления быстрее (не нужно ждать вычисления всех значений в массиве, возвращаемом из функции, чтобы начать обходить их в цикле; возможно, все значения и не понадобятся).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
function fibonacci() { let [prev, curr] = [0, 1]; while (true) { // бесконечный цикл [prev, curr] = [curr, prev + curr]; yield curr; // здесь будет продолжено выполнение после следующего вызова метода next() } } for (let n in fibonacci()) { // ограничим выборку несколькими значениями if (n > 1000) { break; } console.log(n); // 1, 2, 3, 5, 8 ... 987 } console.log('------------'); for (let n in fibonacci()) { // ограничим выборку несколькими значениями if (n > 2000) { break; } console.log(n); // 1, 2, 3, 5, 8 ... 1597 } var fib = fibonacci(); console.log('------------'); console.log(fib.next()); // 1 console.log(fib.next()); // 2 console.log(fib.next()); // 3 console.log(fib.next()); // 5 |
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Iterators_and_Generators
Comprehensions
Выражения для создания генераторов на основе других генераторов.
Выражения для работы с массивами:
1 2 3 4 5 6 |
var ar_a = [0, 1, 2, 3], ar_b = [0, 1, 2, 3], ar_c; ar_c = [a + b for (a in ar_a) for (b in ar_b)]; console.log(ar_c); // ["00", "01", "02", "03", "10", "11", "12", "13", "20", "21", "22", "23", "30", "31", "32", "33"] |
Выражения-генераторы:
1 2 3 4 5 6 7 |
var obj = {a: 1, b: 2, c: 3}; let generator = (x for (x in obj) if (obj[x] >= 2)); for (let i in generator) { console.log(i); } |
for…of
перебирает элементы коллекции (массивы, итераторы, генераторы).
Работа с массивами:
1 2 3 4 5 6 7 8 9 10 |
let arr = [ 3, 5, 7 ]; arr.foo = "hello"; for (let i in arr) { console.log(i); // "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // "3", "5", "7" } |
Работа с генераторами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function fibonacci() { // функция-генератор let [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (let n of fibonacci()) { // прерываемся после 10 if (n > 10) { break; } console.log(n); // 1, 2, 3, 5, 8 } |
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for…of
StructType
1 2 |
const Pixel = new StructType({x:uint32, y:uint32, color:Color}); // Color тоже должен быть StructType new ArrayType(Pixel, 3); |
https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Using_js-ctypes/Declaring_types
Классы (class)
Синтаксический сахар для функций-конструкторов (с возможным наследованием)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Animal { constructor(name) { this.name = name; } sayName() { console.log(this.name); } } class Dog extends Animal { constructor(name) { super(name); } bark() { console.log("Woof!"); } } // аналог в ES3 function Animal(name) { this.name = name; } Animal.prototype.sayName = function() { console.log(this.name); }; function Dog(name) { Animal.call(this, name); } Dog.prototype = new Animal(null); Dog.prototype.bark = function() { console.log("Woof!"); }; |
Более сложный пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Point extends Base { constructor(x,y) { super(); this.px = x, this.py = y; this.r = function() { return Math.sqrt(x*x + y*y); } } get x() { return this.px; } get y() { return this.py; } proto_r() { return Math.sqrt(this.px * this.px + this.py * this.py); } equals(p) { return this.px === p.px && this.py === p.py; } } |
http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes,
http://www.nczonline.net/blog/2012/10/16/does-javascript-need-classes/
Модули
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// вот модуль module DBLayer { export function query(s) { ... } export function connection(...args) { ... } } // использование модуля import DBLayer.*; // импортировать все функции из модуля import DBLayer.{query, connection: attachTo}; // импортировать только нужные функции (причём с возможностью назвать функцию при импорте по-другому) query(“SELECT * FROM books”).format(“escape | split”); attachTo(“/books/store”, { onSuccess: function (response) { ... } }); |
Работа с внешними модулями:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// загрузка из файловой системы module $ = require(“./library/selector.js”); // загрузка модуля из интернета module CanvasLib = require(“http:// ... /js-modules/canvas.js”); // можно использовать напрямую let rect = new CanvasLib.Rectangle({width: 30, height: 40, shadow: true}); // или импортировать только нужный функционал import CanvasLib.{Triangle, rotate}; rotate(-30, new Triangle($.query(...params))); |
http://wiki.ecmascript.org/doku.php?id=harmony:modules,
http://wiki.ecmascript.org/doku.php?id=harmony:modules_examples,
http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders.
Строки-шаблоны
Используются для замены входящих в них плэйсхолдеров на значения локальных переменных.
Преследуют 4 цели: «многострочные» строки, форматирование строк, HTML-экранирование и локализация.
Синтаксис:
1 |
tag`literal${substitution}literal` |
Замена:
1 2 3 4 5 6 7 8 9 10 |
var sub = 1; var text = `Some ${sub}First line Second line`; // получим "Some 1First line // Second line" var total = 30, msg = `The total is ${total} (${total*1.05} with tax)`; console.log(msg); // "The total is 30 (31.5 with tax)" |
Если переменная для замены не определена, будет возбуждено исключение.
В качестве tag можно использовать произвольную функцию.
http://www.nczonline.net/blog/2012/08/01/a-critical-review-of-ecmascript-6-quasi-literals/ (хорошая подробная статья с примерами и рассуждениями об удобстве использования).
Ссылки для более подробного изучения
- http://wiki.ecmascript.org/doku.php?id=harmony:proposals — официальная wiki ECMAScript
- https://developer.mozilla.org/en-US/docs/JavaScript/ECMAScript_6_support_in_Mozilla — описание в MDN
- http://www.slideshare.net/dmitrysoshnikov/falsyvalues-dmitry-soshnikov-ecmascript-6 — неплохая презентация (слайды)
- http://docs.webplatform.org/wiki/concepts/programming/javascript/future — описание на webplatform (пока почти пусто)
- http://espadrine.github.com/New-In-A-Spec/es6/ — краткое описание всех нововведений
- http://kangax.github.com/es5-compat-table/es6/ — сводная таблица реализации новых возможностей в существующих браузерах и node.js
- http://www.nczonline.net/blog/2012/07/24/thoughts-on-ecmascript-6-and-new-syntax/ — что думает Nicholas C. Zakas по поводу ECMAScript 6
- http://habrahabr.ru/post/151690/ — поддержка ECMAScript Harmony в node.js с примерами
Similar Posts
- None Found
LEAVE A COMMENT
Для отправки комментария вам необходимо авторизоваться.