AddConf. Дмитрий Сошников - Будущее ECMAScript

10,591 views

Published on

Published in: Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
10,591
On SlideShare
0
From Embeds
0
Number of Embeds
2,696
Actions
Shares
0
Downloads
38
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

AddConf. Дмитрий Сошников - Будущее ECMAScript

  1. 1. ECMAScriptсегодня и в будущем. Дмитрий Сошников http://dmitrysoshnikov.com
  2. 2. ES5 : Новый API объектов
  3. 3. Два вида свойств:Обычные data-свойства (явная ассоциация имени и значения)Accessor-свойства (геттеры/сеттеры) (неявная ассоциация имени с accessor-функциями)
  4. 4. Работа со свойствамиObject // работа с атрибутами .defineProperty
  5. 5. Работа со свойствамиObject // работа с атрибутами .defineProperty // сразу несколько свойств .defineProperties
  6. 6. Работа со свойствамиObject // работа с атрибутами .defineProperty // сразу несколько свойств .defineProperties // анализ атрибутов (дескриптор) .getOwnPropertyDescriptor
  7. 7. Работа со свойствамиObject // работа с атрибутами // статика .defineProperty .preventExtensions / .isExtensible // сразу несколько свойств // «опечатывание» .defineProperties .seal / .isSealed // анализ атрибутов (дескриптор) // «заморозка» .getOwnPropertyDescriptor .freeze / .isFrozen // список свойств // наследование; прототипы .keys .getPrototypeOf .getOwnPropertyNames .create
  8. 8. Дескриптор data-свойства{ value: 10, // значение writable: true, // только чтение? enumerable: false, // перечислимо в for-in? configurable: true // можно удалить?}
  9. 9. Data-свойствоvar foo = Object.defineProperty({}, “x” { value: 10, writable: true, enumerable: false, configurable: true});
  10. 10. Data-свойствоvar foo = Object.defineProperty(,-, “x” , value: 10, По умолчанию все атрибуты : false writable: true, enumerable: false, Object.defineProperty(foo, “MAX_SIZE” { configurable: true value: 20,}); writable: false, // default enumerable: false, // default configurable: false // default });
  11. 11. Data-свойство var foo = Object.defineProperty(,-, “x” , value: 10, По умолчанию все атрибуты : false writable: true, enumerable: false, Object.defineProperty(foo, “MAX_SIZE” { configurable: true ES3 value: 20, }); writable: false, enumerable: false, configurable: false foo.z = 30; }); Object.defineProperty(foo, “z” , value: 30, writable: true, enumerable: true, configurable: trueСоздание свойства присваиванием -- атрибуты : true });
  12. 12. enumerable: falseES3 ES5Object.prototype.x = 10; Object.defineProperty( Object.prototype, “x”, {var foo = {y: 20}; value: 10 } );for (var k in foo) { for (var k in foo) { console.log(k); // y, x console.log(k); // y} }
  13. 13. Дескриптор accessor-свойства{ get: function () {...}, // чтение значения set: function (v) {...}, // установка значения enumerable: false, // перечислимо в for-in? configurable: true // можно удалить?}
  14. 14. Accessor-свойствоObject.defineProperty(foo, “z” { get: function () { return this.x + this.y; }, set: undefined, enumerable: false, configurable: false});console.log(foo.z); // 30foo.z = 40; // false, только геттерconsole.log(foo.z); // не изменилось - 30
  15. 15. Декларативное объявление геттера/сеттераvar foo = { x: 10, y: 20, get sum() { return this.x + this.y; }};foo.sum; // 30
  16. 16. Список свойств объекта// только enumerable-свойстваObject.keys(foo); // *“y”, “z”+// все родные свойстваObject. getOwnPropertyNames(foo); // *“x”, “y”, “z”+
  17. 17. Фиксация объектовСтатика: запрещает расширение объекта var foo = { Object.isExtensible(Object.preventExtensions(foo)); // false x: 10 foo.bar = 100; // false }; console.log(“bar” in foo); // false
  18. 18. Фиксация объектовСтатика: запрещает расширение объекта var foo = { Object.isExtensible(Object.preventExtensions(foo)); // false x: 10 foo.bar = 100; // false }; console.log(“bar” in foo); // falseОпечатывание (seal): + устанавливает всем свойствам configurable == false Object.isSealed(Object.seal(foo)); // true Object.getOwnPropertyDescriptor(foo, “x”).configurable; // false
  19. 19. Фиксация объектовСтатика: запрещает расширение объекта var foo = { Object.isExtensible(Object.preventExtensions(foo)); // false x: 10 foo.bar = 100; // false }; console.log(“bar” in foo); // falseОпечатывание (seal): + устанавливает всем свойствам configurable == false Object.isSealed(Object.seal(foo)); // true Object.getOwnPropertyDescriptor(foo, “x”).configurable; // falseЗаморозка (freeze): + устанавливает всем свойствам writable == false Object.isFrozen(Object. freeze(foo)); // true foo.y = 100; // false console.log(foo.y); // не изменилось, 20
  20. 20. Получение прототипа объекта Object.getPrototypeOf(foo) === Object.prototype; // true
  21. 21. Прототипное наследование Object.create(proto, [properties])// объект-родительvar foo = { x: 10, y: 20, z: 30};
  22. 22. Прототипное наследование Object.create(proto, [properties])// объект-родитель // наследуем bar от foovar foo = { var bar = Object.create(foo, { x: 10, q: { y: 20, value: 40 z: 30 }}; };console.log(bar.x, bar.y, bar.z, bar.q); // 10, 20, 30, 40
  23. 23. Обычные hash-таблицы без прототипа var foo = Object.create(null); alert(foo); // ?
  24. 24. Обычные hash-таблицы без прототипа var foo = Object.create(null); alert(foo); // errorНет метода toString. Объект fooпустой и ни от кого не наследует.
  25. 25. Будущее > ES6
  26. 26. let : переменные в блоках
  27. 27. Блочная область видимости// ES3if (false) { var a = 10;}alert(a); // ?
  28. 28. Блочная область видимости// ES3var a; // = undefined;if (false) { Все переменные создаются до запуска кода – при входе в контекст. a = 10; Так называемое «поднятие»} (hoisting) переменных.alert(a); // undefinedSee: http://dmitrysoshnikov.com/notes/note-4-two-words-about-hoisting/
  29. 29. Блочная область видимости// ES6 Harmonyif (false) { let a = 10;}alert(a); // ReferenceError
  30. 30. Блочная область видимости// ES3, ES5var data = []; data[0](); // ? data[1](); // ?for (var k = 0; k < 3; k++) { data[2](); // ? data[k] = function () { alert(k); };}
  31. 31. Блочная область видимости// ES3, ES5var data = []; data[0](); // 2var k; data[1](); // 2for (k = 0; k < 3; k++) { data[2](); // 2 data[k] = function () { alert(k); };}
  32. 32. let : блочная область видимостиES3, ES5 ES6for (var k = 0; k < 3; k++) { for (let k = 0; k < 3; k++) { (function (x) { data[x] = function () { data[x] = function () { alert(x); alert(x); }; }; } })(k);}data[0](); // 0 data[0](); // 0
  33. 33. Деструктуризацияили «нестогий pattern-matching»
  34. 34. Деструктуризация : массивы// для массивовlet [x, y] = [10, 20, 30]; // нестрогий matchingconsole.log(x, y); // 10, 20
  35. 35. Деструктуризация: объекты// для объектовlet foo = {value: 100, data: {x: 10, y: 20}};let {value: v, data: {x: x, y: y}} = foo;console.log(v, x, y); // 100, 10, 20
  36. 36. Деструктуризация параметров функцииfunction foo({a: a, b: [x, y]}) { return a + x * y;}let data = {a: 1, b: [2, 3]};foo(data); // 7
  37. 37. Деструктуризация: обмен переменных// обмен двух переменных без третьей?let x = 10;let y = 20;[x, y] = [y, x]; // легко
  38. 38. Замена arguments: ”rest” и ”spread”
  39. 39. Объект arguments// ES3, ES5function foo(name, /* rest */) { var rest = [].slice.call(arguments, 1); var squares = rest.map(function (x) { return x * x}); return squares;}foo(“squares”, 1, 2, 3); // [1, 4, 9]
  40. 40. Прощай, arguments// ES3, ES5function foo(name, /* rest */) { var rest = [].slice.call(arguments, 1); // сложно var squares = rest.map(function (x) { return x * x}); return squares;}foo(“squares”, 1, 2, 3); // *1, 4, 9+
  41. 41. Привет, ”rest”// ES6 aka Harmonyfunction foo(name, …rest) { // настоящий массив var squares = rest.map(function (x) { return x * x}); return squares;}foo(“squares”, 1, 2, 3); // [1, 4, 9]
  42. 42. А также ”spread”// ES6 aka Harmonyfunction bar(x, y, z) { return x + y * z;}let args = [1, 2, 3];bar(…args); // 7bar.apply(null, args); // или так, 7
  43. 43. ”spread” в pattern-matching// ES6 aka Harmonylet args = [“data”, 1, 2, 3];let [name, ...values] = args;console.log(name); // “data”console.log(values); // [1, 2, 3]
  44. 44. Сокращенные нотации
  45. 45. Сокращения в деструктуризации// полная нотацияlet {x: x, y: y, z: z} = {x: 10, y: 20, z: 30};// сокращенная нотацияlet {x, y, z} = {x: 10, y: 20, z: 30};
  46. 46. Короткий синтаксис функций. #-функции// обычные функции[1, 2, 3].map(function (x) { return x * x; }); // [1, 4, 9]// #-функции[1, 2, 3].map(#(x) { x * x }); // [1, 4, 9]Синтаксически: • необязательный return; • # вместо function
  47. 47. Семантика #-функций// обычная функция Динамическиlet object = { связываемый this start: function () { setTimeout(function () { this.continue(); }, 500); }, continue: function () { ... }}; Решения: var that = this;object.start(); // error .bind(this)
  48. 48. Семантика #-функций// #-функции this автоматом связанlet object = { с лексическим контекстом start: function () { setTimeout(#{ this.continue(); }, 500); }, continue: function () { ... }};object.start(); // ok
  49. 49. Семантика #-функций// #-функции Динамический thislet object = { в #-функциях start: # (this) { setTimeout(#{ this.continue(); }, 500); }, continue: # (this) { ... }};object.start(); // ok
  50. 50. Proxy объекты : мета уровень
  51. 51. Proxy-объекты/* handler – обработчик мета-уровня * proto – прототип прокси-объекта */Proxy.create(handler, [proto])/* handler – мета-обработчик * call – проксирование вызова * construct – проксирование конструирования */Proxy.createFunction(handler, [call, [construct]])See: http://wiki.ecmascript.org/doku.php?id=harmony:proxies
  52. 52. Proxy-объекты // original object // proxied object let foo = { let pFoo = Proxy.create({ x: 10, get: function (rcvr, name) { y: 20 console.log(“get: ”, name); }; return foo[name]; }, set: function (rcvr, name, value) {Перехват чтения console.log(“set: ”, name, value); свойства foo[name] = value; }Перехват записи }, Object.getPrototypeOf(foo)); свойства
  53. 53. Proxy-объекты // proxied objectМета-обработчик let pFoo = Proxy.create({ get: function (rcvr, name) {// перехват чтения console.log(“get: ”, name);pFoo.x; // get: x, 10 return foo[name]; },// перехват записи set: function (rcvr, name, value) {pFoo.x = 100; // set: x, 100 console.log(“set: ”, name, value); foo[name] = value;// отображается на оригинале }foo.x; // 100 }, Object.getPrototypeOf(foo));
  54. 54. Callable Proxy-объекты// original object // proxied objectlet foo = {x: 10, y: 20}; let pFoo = Proxy.createFunction({ get: function (rcvr, name) {function callTrap() { console.log(“get: ”, name); console.log(“call”); return foo[name];} }, set: function (rcvr, name, value) {function constructTrap() { console.log(“set: ”, name, value); console.log(“construct”); foo[name] = value;} } }, callTrap, constructTrap);pFoo(10, 20); // “call”new pFoo(100); // “construct” Перехват Перехват вызова конструирования
  55. 55. Proxy : примеры// логгеры (на чтение и запись)Proxy.create(logHandler(object));// множественное наследование (делегирующие примеси)Proxy.create(mixin(obj1, obj2));// noSuchMethodProxy.create(object, noSuchMethod)// Массивы с отрицательными индексами (как в Python)let a = Array.new([1, 2, 3]);console.log(a[-1]); // 3a[-1] = 10; console.log(a); // [1, 2, 10]See: https://github.com/DmitrySoshnikov/es-laboratory/tree/master/examples
  56. 56. Система модулей
  57. 57. Модули в ES3, ES5var Library = (function (global) { /* save original */ var originalLibrary = global.Library; function noConflict() { global.Library = originalLibrary; 1. Создать локальный скоп } 2. Функция восстановления /* implementation */ 3. Имплементация 4. Публичный интерфейс function query() { ... } /* exports, public API */ return { noConflict: noConflict, query: query };})(this);
  58. 58. Модули в ES3, ES5var Library = (function (global) { /* save original */ var originalLibrary = global.Library; function noConflict() { global.Library = originalLibrary; 1. Создать локальный скоп } 2. Функция восстановления /* implementation */ 3. Имплементация 4. Публичный интерфейс function query() { ... } /* exports, public API */ Слишком много return { синтаксического «шума». noConflict: noConflict, Нужен «сахар». query: query };})(this);
  59. 59. Модули в ES6module Library { export function query(s) { ... } export function ajax(...args) { ... }}import Library.*; // импортировать всеimport Library.{query, ajax: xhr}; // импортировать только нужноеquery(“#my-element”).hide();xhr(“/books/store”, { onSuccess: # (response) { ... }})
  60. 60. Модули в ES6module Widgets { var collection= [ ... ]; // приватное свойство function registerWidget(name, ...params) { ... } // приватное ? // внутренний приватный модуль module Register { ... } В дополнение: // вложенный публичный модуль export module Panel { // ошибка, нельзя присвоить export’у export function create() { ... } Widgets.Panel = false; } // ошибка, нет такого export’а // множественный export let bar = Widget.Window export { register: registerWidget }}let panel = Widgets.Panel.create({title: “Options”});
  61. 61. Внешние модули в ES6// на файловой системеmodule $ = “./library/selector.js”;// глобально, из сети; сами определяем имя модуляmodule CanvasLib = “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)));
  62. 62. Спасибо за внимание Дмитрий Сошниковdmitry.soshnikov@gmail.com http://dmitrysoshnikov.com @DmitrySoshnikov

×