Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Одна функция в роли сеттера (геттера) для разных свойств (https://javascript.ru/forum/misc/50082-odna-funkciya-v-roli-settera-gettera-dlya-raznykh-svojjstv.html)

trikadin 11.09.2014 03:51

Одна функция в роли сеттера (геттера) для разных свойств
 
Можно ли сделать одну функцию геттером либо сеттером для разных элементов так, чтобы в момент вызова знать, для какого свойства объекта она была вызвана?

Поясню, в чём суть: имеется несколько разных свойств у одного объекта, геттер которых должен просто возвращать значение, и больше ничего (а вот сеттер уже делает разные интересные вещи). Хочется не писать для каждого из этих свойств свою функцию-геттер, а сделать одну общую и вызывать каждый раз её.

obj= {
    get a() {
        return this._a
    },
    set a(v) {
        // do smth interesting
    },
    get b() {
        return this._b;
    },
    set b(v) {
        // do smth else
    },
    get c() {
        return this._c
    },
    set c(v) {
        // i don't know what to do :-)
    }
}


Хочется это сократить.

Aetae 11.09.2014 05:33

Мб забиндить? Не знаю правда как в этом случае с оптимизацией... Вся надежда на браузер.)

var obj = {},
    props = {
        "a": 1,
        "b": 1,
        "c": 1,
    };
function setGet(isSet, prop, val){
    if(isSet){
        console.log('set ' + prop + ' = ' + val);
        return props[prop] = val;
    }else{
        console.log('get ' + prop + ' = ' + props[prop]);
        return props[prop]
    }
};

for(var prop in props) if(props.hasOwnProperty(prop)){
    Object.defineProperty(obj, prop, {
        set: setGet.bind(obj, true, prop), 
        get: setGet.bind(obj, false, prop),
        enumerable : true,
        configurable : true
    });
}

var x = obj.b;
obj.b = x + 10;


В ES6 есть какраз подходящая для этого няшная штука, Proxy:
var props = {
    "a": 1,
    "b": 1,
    "c": 1,
};
function setGet(obj, prop, val, proxy){
    var isSet = !!proxy; //при get приходит только три аргумента, где третий proxy
    if(isSet){
        console.log('set ' + prop + ' = ' + val);
        return obj[prop] = val;
    }else{
        console.log('get ' + prop + ' = ' + obj[prop]);
        return obj[prop]
    }
};

var obj = new Proxy(props, {
    get: setGet, 
    set: setGet  
});
var x = obj.b;
obj.b = x + 10;
Но увы без дополнительной настройки пока работать будет только в FF.
Вообще прокси крутая штука, которая может гораздо больше чем я привёл в пример.)

MallSerg 11.09.2014 12:23

Не совсем понятное объяснение ((
т.е. у объекта есть свойства у которых есть функции
и проблема в том что для каждого свойства есть приходится писать однотипную функцию?

тогда почему не использовать наследование?
<!Doctype html>
<html><head><style></style></head><body>
<a id="fr"></a>
<script type='text/javascript'>
	obj_A ={
		set:function set (){ return "seter val = " + this.val },
		get:function get (){ return "seter val = " + this.val },
	}
	obj_B = function ff (){ this.val = "ничегошеньки в val нетути" }
	obj_B.prototype = obj_A;
	var obj = {};

	obj.a = new obj_B;
	obj.b = new obj_B;
	obj.c = new obj_B;
	obj.d = new obj_B;
	
	obj.a.val = "im A";
	obj.b.val = "im B";
	obj.c.val = "im C";
	
	document.all["fr"].innerHTML = ""+ 
		 obj.a.get() +"<br>"+
		 obj.b.get() +"<br>"+
		 obj.c.get() +"<br>"+
		 obj.d.get();
</script></body></html>

trikadin 11.09.2014 14:01

Aetae, круто, про вот не знал про bind, позор на мою голову. Proxy -- и правда красивое решение, но у меня сразу даже пример ваш не получилось запустить:haha:

По-хорошему, надо попробовать оба варианта и проверить на производительность, ибо у меня она как раз важна, так как рисуется графика.

MallSerg, суть именно в геттерах и сеттерах. В том, что потом функция будет вызываться, когда ты просто делаешь obj.a=0
Вот, почитай.
http://habrahabr.ru/post/66242/

Aetae 11.09.2014 16:25

Имхо если производительность сильно критична, то стоит забыть о вызовах функций на каждый чих, и вообще смотреть в сторону всяких TypedArray. (Посоветовал бы asm.js, но в текущем его виде человеку им пользоваться невозможно:) )

trikadin 11.09.2014 16:45

Aetae, ещё не понял, насколько критична. Сначала допишу, затормозит -- буду оптимизировать) Преждевременно этим заниматься, как известно, грех.


Часовой пояс GMT +3, время: 09:17.