ݺߣ

ݺߣShare a Scribd company logo
Immutable Data
Неизменяемые данные в приложении:
что, зачем и как
логитип moscow js
Дмитрий Кунин, AT-Consulting
Что это такое?
2 / 45
Immutable + Persistent
3 / 45
Принцип работы
varlist=Immutable.List.of(1,2,3);
varlist2=list.push(4);
console.log(list.toJS())//[1,2,3]
console.log(Immutable.is(list,list2))//false
4 / 45
Принцип работы
List.prototype.push=function(value){
//Делаемклон
varclone=deepCopy(this);
//Меняемзначениевклоне
clone[clone.length]=value;
//Вовзращаемклон
returnclone;
}
5 / 45
varlist=[];
for(vari=0;i<1000000;i++){
list.push(i);
}
vanilla: 83 ms
varlist=mori.vector();
for(vari=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.js
mori
seamless-
immutable
immutato
pim
seti
texo
ancient-oak
15 / 45
Зачем использовать?
16 / 45
Зачем использовать?
Решать проблемы!
17 / 45
Мутирующие объекты могут мутировать
:)))
varidentity="Федор";
...
identity="ФедорПетрович";
...
identity="Косой";
18 / 45
Интерфейс должен
следить за изменениями
19 / 45
Слушатели событий
varuserData={
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
varuserData={...};
Object.observe(userData,...);
userData.name.nickname="Косой";//Изменениянезамечены
21 / 45
"Грязная" проверка Грязные танцы
varuserData={
dirty:false,
_raw:{name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"},
get:function(key){
returnthis._raw[key]
},
set:function(key,newValue){
this._raw[key]=newValue;
this.dirty=true;
}
}
22 / 45
funtionrenderProfile(data){
if(!data.dirty)return;
data.dirty=false;
...
}
userData.set("online",true);
renderProfile(userData);//ok
23 / 45
funtionrenderProfile(data){
if(!data.dirty)return;
data.dirty=false;
}
funtionrenderContactItem(data){
if(!data.dirty)return;
data.dirty=false;
}
data.set("online",true);
renderProfile(userData);//ok
renderContactItem(userData);//dirty=false;norender
24 / 45
Сравнение Immutable объектов / списков
varuser1=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
25 / 45
Сравнение Immutable объектов / списков
varuser1=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
varuser2=user1.set("name","Косой");
console.log(Immutable.is(user1,user2));//false
26 / 45
Сравнение Immutable объектов / списков
varuser1=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
varuser2=user1.set("name","Косой");
console.log(Immutable.is(user1,user2));//false
varuser3=user2.set("name","ФедорПетрович");
console.log(Immutable.is(user1,user3));//true
27 / 45
Глубокое сравнение
varuser1=Immutable.Map({
skills:Immutable.Map({str:23,int:18,luck:99}),
category:Immutable.Map({gentelaman:true})
});
28 / 45
Глубокое сравнение
varuser1=Immutable.Map({
skills:Immutable.Map({str:23,int:18,luck:99}),
category:Immutable.Map({gentelaman:true})
});
varuser2=user1.setIn(["skills","int"],0);
Immutable.is(user2,user1)
29 / 45
Глубокое сравнение
varuser1=Immutable.Map({
skills:Immutable.Map({str:23,int:18,luck:99}),
category:Immutable.Map({gentelaman:true})
});
varuser2=user1.setIn(["skills","int"],0);
Immutable.is(user2,user1)
Immutable.is(second.get("skills"),first.get("skills"))//fal
30 / 45
Глубокое сравнение
varuser1=Immutable.Map({
skills:Immutable.Map({str:23,int:18,luck:99}),
category:Immutable.Map({gentelaman:true})
});
varuser2=user1.setIn(["skills","int"],0);
Immutable.is(user2,user1)
Immutable.is(second.get("skills"),first.get("skills"))//fal
Immutable.is(second.get("category"),first.get("category"))//
31 / 45
Плюшки
32 / 45
Отсутствие побочных эффектов
functionupdateValueAndLog(updateFunction){
vardata={name:"Федор"};
updateFunction(data);
console.log(data);//?
}
33 / 45
Отсутствие побочных эффектов
functionupdateValueAndLog(updateFunction){
vardata={name:"Федор"};
updateFunction(data);
console.log(data);//?
}
varuser=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
varuserClone=user; 34 / 45
Практически бесплатный
undo/redo
35 / 45
0:00
36 / 45
Как пользоваться?
37 / 45
Массивы
varlist1=Immutable.List.of(1,2);
assert(list1.size===2);
varlist2=list1.push(3,4,5);
assert(list2.size===5);
varlist3=list2.unshift(0);
assert(list3.size===6);
varlist4=list1.concat(list2,list3);
assert(list4.size===13);
assert(list4.get(0)===1);
38 / 45
Объекты
varuser1=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
varuser2=user1.set("name","Косой");
user1.get("name");//"ФедорПетрович"
user2.get("name");//"Косой"
39 / 45
Принимает и возвращает обычные JS
объекты
varuser1=Immutable.Map({
name:"ФедорПетрович",
online:true,
profilePic:"/url/user1.png"});
varstat ={name:"Косой",age:37};
varuser2=user1.merge(stat);
console.log(user2.toJS())
//{name:"Косой",
// online:true,
// profilePic:"/url/user1.png",
// age:37} 40 / 45
Многое другое
Stack
OrderedMap
Set
OrderedSet
Record
41 / 45
Групповые операции
vartraits1=Immutable.List.of("communication","luck","skill"
vartraits2=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.in
demo + libs : bit.ly/imm-js
twitter : DKunin
Skype : dkunin1985

More Related Content

"Immutable данные в JS приложениях", Дмитрий Кунин, MoscowJS 20