Matreshka.js — MK.Object

от автора

В предыдущих статьях мы познакомились с общими принципами Матрешки: привязка элементов, события, наследование. В конце предыдущей статьи я задал себе вопрос: «Как разграничить состояние приложения (показать ли пользователю пароль) и данные приложения (логин, пароль, «запомнить меня»)».

Класс, который нам в этом поможет, называется MK.Object, который наследуется от класса Matreshka. Идея проста: у нас есть множество ключей, отвечающих за данные в экземпляре класса и мы считаем, что остальные свойства отвечают лишь за состояние приложения и не являются бизнес моделью.

Как устроено множество ключей

За множество ключей отвечает псевдоприватное свойство ._keys, которое является объектом со значениями, которые нам безразличны. Массив бы нам не подошел, потому что, перед добавлением нового ключа надо было бы проверять, есть ли ключ в массиве, а при удалении, пришлось бы узнавать индекс, затем сдвигать следующие элементы. В случае объекта, мы получаем полноценное множество строк, для добавления нового ключа не нужно проверять его наличие, а для удаления требуется лишь вызов оператора delete.

Для того, чтоб установить свойство, которое отвечает за данные, используется метод .jset:

var mkObject = new MK.Object(); mkObject.jset( 'a', 1 ); console.log( mkObject.toJSON() ); // { a: 1 } 


Документация к .jset: finom.github.io/matreshka/docs/Matreshka.Object.html#jset
Документация к .toJSON: finom.github.io/matreshka/docs/Matreshka.Object.html#toJSON
Теперь можем работать с новым свойством как обычно:

var mkObject = new MK.Object(); mkObject.jset( 'a', 1 ); mkObject.a = 2; console.log( mkObject.toJSON() ); // { a: 2 } 

В том числе, мы можем использовать унаследованные от класса Matreshka методы:

mkObject.bindElement( 'a', '.my-element' ); mkObject.on( 'change:a', handler ); 

Если мы установим свойство, не добавив его ключ в множество ключей, в результате работы метода .toJSON мы не увидим этого свойства:

var mkObject = new MK.Object(); mkObject.jset( 'a', 1 ); mkObject.b = 3; console.log( mkObject.toJSON() ); // { a: 1 } 

Можно добавить ключи в список ключей, используя метод .addJSONKeys
Дока: finom.github.io/matreshka/docs/Matreshka.Object.html#addJSONKeys

mkObject.addJSONKeys( 'b', 'c' ); 

Здесь следует важное правило: если вы не уверены наверняка, какие свойства должны попадать в результат работы функции .toJSON, всегда используйте .jset вместо обычного присваивания. Если ключи известны, то, лично я, предпочитаю всегда задавать данные по умолчанию:

var MyClass = Class({ 	'extends': MK.Object, 	constructor: function( data ) { 		this 			.initMK() 			.jset({ // данные по умолчанию 				a: 1, 				b: 2, 				c: 3 			}) 			.set( data ) // кастомные данные (data - обычный объект с данными) 		; 	} }); 

Обратите внимание на вызов .initMK. Здесь он инициализирует не только объекты событий и «специальных» свойств, но и объект-множество ключей. Кроме этого, он добавляет необходимые обработчики событий вызывая событие "modify" при изменении данных. Пример:

var mkObject = new MK.Object(); mkObject.jset({ 	a: 1, 	b: 2 }); mkObject.c = 3;  mkObject.on( 'modify', function() { 	alert( 'Data is changed' ); });  mkObject.a = 4; // вызывает обработчик mkObject.b = 5; // вызывает обработчик mkObject.c = 6; // обработчик не вызывается, так как ключ "c" не обозначен, как данные 

Если передать классу аргумент в виде объекта, он интерпретирует его, как данные:

var mkObject = new MK.Object({ a: 1, b: 2 }); // то же самое, что и var mkObject = new MK.Object(); mkObject.jset({ a: 1, b: 2 }); 

Перебрать данные можно с помощью метода .each:

var mkObject = new MK.Object(); mkObject.jset({ 	a: 1, 	b: 2 }); mkObject.c = 3; mkObject.each( function( item, key ) { 	console.log( key ); }); // выведет 'a', 'b' 

Дока: finom.github.io/matreshka/docs/Matreshka.Object.html#each

Проверить, есть ли в объекте какое-нибудь свойство можно с помощью метода .hasOwnProperty

var mkObject = new MK.Object(); mkObject.jset( 'a', 1 ); mkObject.b = 2; alert( mkObject.hasOwnProperty( 'a' ) ); // true alert( mkObject.hasOwnProperty( 'b' ) ); // false ('b' не является данными) 

Это позволяет юзать конструкцию for..in, как для обычного объекта:

for( var i in mk ) if( mk.hasOwnProperty( i ) ) { 	doSomething(i, mk[i]) } 

Есть еще ряд методов, имена которых говорят сами за себя:
.keyOf, который ищет ключ по значению и возвращает ключ (аналог .indexOf для массива).
.keys, возвращающий массив ключей.
.removeJSONKeys, удаляющий ключи из множества ключей, отвечающих за данные.

Взгляните на измененный пример из предыдущей статьи: jsbin.com/ATAPUCo/6/
В конструкторе мы задаём данные по умолчанию:

	... 	constructor: function () { 		this 			.initMK() 			.jset({ // вот здесь 				userName: '', 				password: '', 				rememberMe: true 			}) 			.bindings() 			.events(); 	}, 	... 

А затем, вместо того, чтоб вручную конструировать объект, который должен быть послан на сервер, мы вызываем метод .toJSON:

	... 	login: function () { 		if (this.isValid) { 			alert( JSON.stringify( this.toJSON() ) ); 		} 		return this; 	} 	... 

В завершение

Теперь мы знаем, как отделить данные Матрешки от состояний, которые не интересны бекенду. Замечательно. Но что, если нам нужно множество данных? Что-то типа массива или коллекции из Backbone.js. Решение — класс MK.Array, о котором я расскажу в следующей статье.

Спасибо, что прочли статью до конца. Всем добра и хорошего кодинга.

ссылка на оригинал статьи http://habrahabr.ru/post/196886/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *