"immutable данные в js приложениях", Дмитрий Кунин, moscowjs...

Post on 16-Jul-2015

230 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Immutable DataНеизменяемые данные в приложении:

что, зачем и каклогитип moscow js

Дмитрий Кунин, AT-Consulting

Что это такое?

2 / 45

Immutable + Persistent

3 / 45

Принцип работы

var list = Immutable.List.of(1,2,3);var list2 = list.push(4);

console.log(list.toJS()) // [1,2,3] console.log(Immutable.is(list,list2)) // false

4 / 45

Принцип работы

List.prototype.push = function(value){ // Делаем клон var clone = deepCopy(this); // Меняем значение в клоне clone[clone.length] = value; // Вовзращаем клон return clone; }

5 / 45

var list = [];for(var i=0;i < 1000000;i++) { list.push(i);}

vanilla: 83 ms

var list = mori.vector();for (var i=0; i < 1000000; i++) { mori.conj(list, i);}

mori: 288 ms

Скорость работы

6 / 45

Направленный ациклический граф

7 / 45

8 / 45

9 / 45

10 / 45

11 / 45

12 / 45

13 / 45

14 / 45

Готовые библиотеки

immutable.jsmoriseamless-immutableimmutatopimsetitexoancient-oak

15 / 45

Зачем использовать?

16 / 45

Зачем использовать?

Решать проблемы!

17 / 45

Мутирующие объекты могут мутировать:)))

var identity = "Федор";...identity = "Федор Петрович";...identity = "Косой";

18 / 45

Интерфейс долженследить за изменениями

19 / 45

Слушатели событийvar userData = { name:"Федор", online:true, profilePic: "/url/user1.png" };

Object.observe(userData, function(changes){ rerenderProfile();});

userData.name = "Федор Петрович";userData.online = false;userData.profilePic = "/newurl/user2.png";

20 / 45

var userData = { ... };Object.observe(userData, ... );userData.name.nickname = "Косой"; // Изменения не замечены

21 / 45

"Грязная" проверка Грязные танцыvar userData = { dirty: false, _raw: { name: "Федор Петрович", online: true, profilePic: "/url/user1.png"}, get: function(key){ return this._raw[key] }, set: function(key, newValue){ this._raw[key] = newValue; this.dirty = true; }}

22 / 45

funtion renderProfile(data) { if(!data.dirty) return; data.dirty = false; ...}

userData.set("online", true);

renderProfile(userData); // ok

23 / 45

funtion renderProfile(data) { if(!data.dirty) return; data.dirty = false;}

funtion renderContactItem(data) { if(!data.dirty) return; data.dirty = false;}

data.set("online", true);

renderProfile(userData); // okrenderContactItem(userData); // dirty = false; no render

24 / 45

Сравнение Immutable объектов / списковvar user1 = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

25 / 45

Сравнение Immutable объектов / списковvar user1 = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

var user2 = user1.set("name", "Косой");console.log(Immutable.is(user1, user2)); // false

26 / 45

Сравнение Immutable объектов / списковvar user1 = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

var user2 = user1.set("name", "Косой");console.log(Immutable.is(user1, user2)); // false

var user3 = user2.set("name", "Федор Петрович");console.log(Immutable.is(user1, user3)); // true

27 / 45

Глубокое сравнениеvar user1 = Immutable.Map({ skills: Immutable.Map({str: 23, int: 18, luck: 99}), category: Immutable.Map({gentelaman: true})});

28 / 45

Глубокое сравнениеvar user1 = Immutable.Map({ skills: Immutable.Map({str: 23, int: 18, luck: 99}), category: Immutable.Map({gentelaman: true})});var user2 = user1.setIn(["skills", "int"], 0);

Immutable.is(user2 , user1)

29 / 45

Глубокое сравнениеvar user1 = Immutable.Map({ skills: Immutable.Map({str: 23, int: 18, luck: 99}), category: Immutable.Map({gentelaman: true})});var user2 = user1.setIn(["skills", "int"], 0);

Immutable.is(user2 , user1) Immutable.is(second.get("skills") , first.get("skills")) //false

30 / 45

Глубокое сравнениеvar user1 = Immutable.Map({ skills: Immutable.Map({str: 23, int: 18, luck: 99}), category: Immutable.Map({gentelaman: true})});var user2 = user1.setIn(["skills", "int"], 0);

Immutable.is(user2 , user1) Immutable.is(second.get("skills") , first.get("skills")) //falseImmutable.is(second.get("category"), first.get("category")) //true

31 / 45

Плюшки

32 / 45

Отсутствие побочных эффектов

function updateValueAndLog(updateFunction) { var data = {name: "Федор"}; updateFunction(data); console.log(data); // ?}

33 / 45

Отсутствие побочных эффектов

function updateValueAndLog(updateFunction) { var data = {name: "Федор"}; updateFunction(data); console.log(data); // ?}

var user = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

var userClone = user; 34 / 45

Практически бесплатныйundo/redo

35 / 45

0:00

36 / 45

Как пользоваться?

37 / 45

Массивыvar list1 = Immutable.List.of(1, 2);assert(list1.size === 2);

var list2 = list1.push(3, 4, 5);assert(list2.size === 5);

var list3 = list2.unshift(0);assert(list3.size === 6);

var list4 = list1.concat(list2, list3); assert(list4.size === 13);

assert(list4.get(0) === 1);

38 / 45

Объектыvar user1 = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

var user2 = user1.set("name", "Косой");

user1.get("name"); // "Федор Петрович"user2.get("name"); // "Косой"

39 / 45

Принимает и возвращает обычные JSобъектыvar user1 = Immutable.Map({ name: "Федор Петрович", online: true, profilePic: "/url/user1.png"});

var stat = { name:"Косой", age: 37 };var user2 = user1.merge(stat);

console.log(user2.toJS()) // { name: "Косой", // online: true, // profilePic: "/url/user1.png",// age: 37 } 40 / 45

Многое другое

StackOrderedMapSetOrderedSetRecord

41 / 45

Групповые операцииvar traits1 = Immutable.List.of("communication","luck","skill"var traits2 = traits1.withMutations(function (traits) { traits.push("dexterity").push("power").push("speed");});assert(traits1.size === 3);assert(traits2.size === 6);

42 / 45

Стоит пощупать вследующем проекте?

43 / 45

Стоит пощупать вследующем проекте?

Да!

44 / 45

Вопросы?Дмитрий Кунин

vcard : dkun.indemo + libs : bit.ly/imm-jstwitter : DKuninSkype : dkunin1985

top related