Начну издалека. С браузеров. Новинками браузеростроения интересуюсь не так уж и часто, но вот однажды, со скуки, решил посмотреть, что javascript грядущий нам готовит и что с этого нам могут предложить современные браузеры. Речь идет, само собой, не об ECMAScript 5, а уже о ECMAScript 6 ECMAScript Harmony. Через пару минут серфинга я наткнулся на такую вот сводную табличку. Не самая актуальная — Chrome, например, довольно давно поддерживает Proxy. Само собой, разброд оказался еще тот. В браузере это использовать пока не реально.
В браузере. А на сервере? На сервере нет необходимости поддерживать зоопарк различных браузеров. Node.js использует V8 — тот же javascript движок, что и Chrome, соответственно, он должен поддерживать те же новые возможности языка.
Полный энтузиазма, я накидал тестик с использованием let и запустил node.
-«А фиг тебе,» — сказала Нода — «синтаксическая ошибка»!
И, погрустнев, я ненадолго оставил эту затею. Как выяснилось позже — зря.
Node с бешеной скоростью меняла версии. В ченджлогах постоянно писалось про смену версий V8. И где долгожданная гармония?
Несколько дней назад вышла очередная, я зарылся в гугл и почти сразу осознал каким был дураком. Оказывается, node.js относительно давно поддерживает флаг запуска --harmony и несколько других:
--harmony_typeof (enable harmony semantics for typeof)
--harmony_scoping (enable harmony block scoping)
--harmony_modules (enable harmony modules (implies block scoping))
--harmony_proxies (enable harmony proxies)
--harmony_collections (enable harmony collections (sets, maps, and weak maps))
--use_strict (enforce strict mode) //немного не по теме, но нам пригодится
Запустил. Протестировал. Работает:)
Итак, что мы имеем в Node.js из ECMAScript Harmony на данный момент?
Пока не так уж и много. Простого объявления классов пока нет, можете не облизываться. Однако, как минимум, из-за Proxy на новые возможности стоит обратить внимание.
Константы
Единственная из возможностей Harmony в V8 что включена по умолчанию, без всяких флагов, да и многие, думаю, ей уже постоянно пользуются.
Раньше в js писали «константы» капсом, и некоторые, тем же капсом, в надежде что к ним прислушаются, оставляли комментарии в стиле:
var CONST_C=1;//НЕ ИЗМЕНЯТЬ!!!111
Теперь всё проще:
const C=1;
C=2;
console.log(C);//=>1
В strict mode область видимости констант аналогична let, об этом далее.
let и блоки
Работает только в strict mode. Если нет желания постоянно его прописывать — запускайте с флагом --use_strict. Правда, только если только если не особо активно используете сторонние библиотеки — очень многие без, например, arguments.callee или with жить не могут.
let это новый var, в целом аналогичен ему, кроме одного — область видимости ограничена блоком.
Выглядит это так:
"use strict";
let i=1;
{
let i=2;
console.log(i);//=>2;
}
console.log(i);//=>1;
for(let i=0;i<5;i++) console.log(i);//=> 0, 1, 2, 3, 4
console.log(i);//=>1;
if(true) var j=1;//OK
if(true) let k=1;//!!!Так не делать - SyntaxError: Illegal let declaration in unprotected statement context.
//и, как писалось выше:
const C=1;
{
const C=2;
console.log(C);//=>2;
}
console.log(C);//=>1;
Proxy
Пожалуй, самая интересная из возможностей, доступных на данный момент. Выводит рефлексию в javascript на новый уровень. Например, позволяет динамически создавать несуществующие методы:
var object=Proxy.create({
get:function(proxy,name){
return function(){
console.log(name);
};
}
});
object.test(); //=>"test"
object.privet();//=>"privet"
Когда-то сомневался, что такая штука в javascript вообще появится:)
С помощью Proxy.createFunction можно сделать, например, исполняемые инстансы классов и еще множество вкусностей.
Хорошо расписано тут.
Set, Map и WeakMap
Set хранит уникальные значения, Map и WeakMap — ассоциативные массивы, где ключами могут выступать любые объекты и функции. По идее, WeakMap отличается от Map тем, что при удалении всех ссылок на объект, представляющий ключ, удаляется и пара ключ-значение из массива. Однако, в данной реализации V8, Map и WeakMap — одно и то же, т.к. в ней пока не реализован итератор; во избежании утечек памяти, в Map мусор собирается аналогично WeakMap.
var st=new Set;
st.add(5);
st.add(5);
console.log(st.has(5));//=>true
st.delete(5);
console.log(st.has(5));//=>false
st.add(console);
console.log(st.has(console));//=>true
var map=new WeakMap;
var obj={foo:"bar"};
map.set(obj,"val");
console.log(map.get(obj));//=>"val"
map.delete(obj);
console.log(map.get(obj));//=>undefined
typeof null
//раньше
console.log(typeof null);//=>"object"
//теперь
console.log(typeof null);//=>"null"
Вот такой вот спорный момент. Может поломать старый код, так что флаг --harmony эту фичу не включает. Если есть желание использовать — запускайте с --harmony_typeof.
Модули
А теперь о печальном. Хоть и имеются флаг --harmony_modules и юнит-тесты системы модулей в стиле Harmony, помучить их мне не удалось. При попытке использования — либо segmentation fault, либо синтаксическая ошибка. Кто разобрался — буду благодарен за подсказку.
Как собрать дабы запускать без флагов — тоже не разобрался, да и не особо пытался:) Правил флажки в deps/v8/src/flag-definitions.h, но ничего кроме segmentation fault так и не получил. Буду благодарен за подсказку и в этом.
До утверждения спецификации еще далеко, большинство вкусных возможностей (тык, тык, тык, тык, тык и т.д.) еще не реализовано в V8, но, вроде, уже неплохо:)
Автор: rock