3. Два вида свойств:
Обычные data-свойства
(явная ассоциация имени и значения)
Accessor-свойства (геттеры/сеттеры)
(неявная ассоциация имени с accessor-функциями)
5. Работа со свойствами
Object
// работа с атрибутами
.defineProperty
// сразу несколько свойств
.defineProperties
6. Работа со свойствами
Object
// работа с атрибутами
.defineProperty
// сразу несколько свойств
.defineProperties
// анализ атрибутов (дескриптор)
.getOwnPropertyDescriptor
7. Работа со свойствами
Object
// работа с атрибутами // статика
.defineProperty .preventExtensions / .isExtensible
// сразу несколько свойств // «опечатывание»
.defineProperties .seal / .isSealed
// анализ атрибутов (дескриптор) // «заморозка»
.getOwnPropertyDescriptor .freeze / .isFrozen
// список свойств // наследование; прототипы
.keys .getPrototypeOf
.getOwnPropertyNames .create
8. Дескриптор data-свойства
{
value: 10, // значение
writable: true, // только чтение?
enumerable: false, // перечислимо в for-in?
configurable: true // можно удалить?
}
12. enumerable: false
ES3 ES5
Object.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. Дескриптор accessor-свойства
{
get: function () {...}, // чтение значения
set: function (v) {...}, // установка значения
enumerable: false, // перечислимо в for-in?
configurable: true // можно удалить?
}
16. Список свойств объекта
// только enumerable-свойства
Object.keys(foo); // *“y”, “z”+
// все родные свойства
Object. getOwnPropertyNames(foo); // *“x”, “y”, “z”+
17. Фиксация объектов
Статика: запрещает расширение объекта
var foo = {
Object.isExtensible(Object.preventExtensions(foo)); // false x: 10
foo.bar = 100; // false };
console.log(“bar” in foo); // false
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. Фиксация объектов
Статика: запрещает расширение объекта
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
24. Обычные hash-таблицы без
прототипа
var foo = Object.create(null);
alert(foo); // error
Нет метода toString. Объект foo
пустой и ни от кого не наследует.
28. Блочная область видимости
// ES3
var a; // = undefined;
if (false) { Все переменные создаются до
запуска кода – при входе в контекст.
a = 10;
Так называемое «поднятие»
} (hoisting) переменных.
alert(a); // undefined
See: http://dmitrysoshnikov.com/notes/note-4-two-words-about-hoisting/
30. Блочная область видимости
// ES3, ES5
var data = []; data[0](); // ?
data[1](); // ?
for (var k = 0; k < 3; k++) { data[2](); // ?
data[k] = function () {
alert(k);
};
}
31. Блочная область видимости
// ES3, ES5
var data = []; data[0](); // 3
var k; data[1](); // 3
for (k = 0; k < 3; k++) { data[2](); // 3
data[k] = function () {
alert(k);
};
}
32. let : блочная область видимости
ES3, ES5 ES6
for (var k = 0; k < 3; k++) { for (let k = 0; k < 3; k++) {
let x = k;
(function (x) {
data[x] = function () {
data[x] = function () {
alert(x);
alert(x);
};
}; }
})(k);
}
data[0](); // 0 data[0](); // 0
39. Объект arguments
// ES3, ES5
function 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. Прощай, arguments
// ES3, ES5
function 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. Привет, ”rest”
// ES6 aka Harmony
function foo(name, …rest) { // настоящий массив
var squares = rest.map(function (x) { return x * x});
return squares;
}
foo(“squares”, 1, 2, 3); // [1, 4, 9]
42. А также ”spread”
// ES6 aka Harmony
function bar(x, y, z) {
return x + y * z;
}
let args = [1, 2, 3];
bar(…args); // 7
bar.apply(null, args); // или так, 7
43. ”spread” в pattern-matching
// ES6 aka Harmony
let args = [“data”, 1, 2, 3];
let [name, ...values] = args;
console.log(name); // “data”
console.log(values); // [1, 2, 3]
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. Короткий синтаксис функций.
#-функции
// обычные функции
[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. Семантика #-функций
// обычная функция Динамически
let object = { связываемый this
start: function () {
setTimeout(function () { this.continue(); }, 500);
},
continue: function () { ... }
}; Решения:
var that = this;
object.start(); // error
.bind(this)
48. Семантика #-функций
// #-функции this автоматом связан
let object = { с лексическим контекстом
start: function () {
setTimeout(#{ this.continue(); }, 500);
},
continue: function () { ... }
};
object.start(); // ok
49. Семантика #-функций
// #-функции Динамический this
let object = { в #-функциях
start: # (this) {
setTimeout(#{ this.continue(); }, 500);
},
continue: # (this) { ... }
};
object.start(); // ok
57. Модули в ES3, ES5
var 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. Модули в ES3, ES5
var 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. Модули в ES6
module 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. Модули в ES6
module 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. Внешние модули в 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. Спасибо за внимание
Дмитрий Сошников
dmitry.soshnikov@gmail.com
http://dmitrysoshnikov.com
@DmitrySoshnikov