объекты и работа с ними
просьба сильно не пинать, а объяснить и/или дать ссылку на хороших мануал, только пытаюсь разобраться с ООП
есть объект имеющий древовидную структуру:
obj={
func:{
msg1: 'fm1...',
msg2: 'fm2...',
msg3: 'fm3...',
msg4: 'fm4...',
showF: showMsg
},
errs:{
msg1: 'em1...',
msg2: 'em2...',
msg3: 'em3...',
msg4: 'em4...',
showE: showMsg
},
// и так далее
show: showMsg
};
function showMsg(m){
alert(m)
}
obj.show(obj.func.msg3)
как переделать этот код, чтобы: можно было обратиться сразу к внутреннемому объекту (например, к func) и в параметрах, указывать не полный идентификатор объекта (obj.func.msg3), а только последний (msg3), т.е. как-то так:
obj.showF('msg3')
с передачей значения/указателя (msg3) - пробовал через this в функции showMsg() но видимо, не до конца понимаю куда, что ссылается, в итоге, получаю ссылку на объект, вместо текста сообщения с изменением имени (obj.func.showF на obj.showF) - вообще не получилось, видимо, как-то не правильно создаю указатель |
как изменить имя - вроде бы разобрался (в принципе-то, банально), но получилось только вне объекта:
obj.showF=obj.func.showF; а хотелось бы - изнутри, но конструкция вида: obj.showF: obj.func.showF возвращает ошибку |
Цитата:
obj={
func:{
msg1: 'fm1...',
msg2: 'fm2...',
msg3: 'fm3...',
msg4: 'fm4...'
},
errs:{
msg1: 'em1...',
msg2: 'em2...',
msg3: 'em3...',
msg4: 'em4...'
},
// и так далее
showF: showMsg
};
obj.showF = obj.showF.bind(obj.func);
function showMsg(m){
alert(this[m])
}
obj.showF('msg3');
|
obj={
func:{
msg1: 'fm1...',
msg2: 'fm2...',
msg3: 'fm3...',
msg4: 'fm4...',
},
errs:{
msg1: 'em1...',
msg2: 'em2...',
msg3: 'em3...',
msg4: 'em4...',
},
// и так далее
showF: showF,
showE: showE
};
function showF(m){
alert(this.func[m])
}
function showE(m){
alert(this.errs[m])
}
obj.showE("msg3"); obj.showF("msg4")
так штоле? |
protoquest, да, вроде бы так, спасибо
|
protoquest,
а возможно - без указания this.func[m] в функции? т.е. как-то так:
function showE(m){
alert(this[m])
}
? а в оптимале, чтобы была вообще одна функция, а в зависимости от места вызова применялся - нужный контекст т.е. если вызвано из объекта obj.func то и контекст брался этого объекта |
Cache,
хотя, возможно, через жопу сделать, используя bind, но не нужно. У Вас на самом деле нет четкого понимания, чего Вы на самом деле хотите.
obj={
func:{
msg1: 'fm1...',
msg2: 'fm2...',
msg3: 'fm3...',
msg4: 'fm4...',
},
errs:{
msg1: 'em1...',
msg2: 'em2...',
msg3: 'em3...',
msg4: 'em4...',
},
// и так далее
};
obj.showF = show.bind(obj.func)
obj.showE = show.bind(obj.errs)
function show(m){
alert(this[m])
}
obj.showE("msg3"); obj.showF("msg4")
|
destus,
спасибо, не увидел ваш ответ сразу - то что нужно |
Цитата:
showMsg(obj.func.msg3)вот и пытаюсь понять плюсы и минусы метода, и его удобства |
Цитата:
|
Cache,
Вас вообще не в ту степь прет. это почти то же самое, что
obj.showF = function(m){alert(obj.func[m])}
|
Цитата:
|
protoquest,
как же сказал выше - только учусь, и ООП - для меня темный лес... Суть задачи, хочу обойтись без switch при обработке ответа от сервера, имеющего вид: Код:
KEY_VALUEVALUE и SUBVALUE - подробности например: ERROR_SQL или BAD_KEY в зависимости от этого, хочу вызывать нужную функцию, например, при BAD_KEY нужно вызвать showMsg() с сообщением об ошибке введенного ключа, аналогично при других ошибках с ключом BAD_ а при ERROR_SQL - нужно запустить функцию-таймер, которая повторит запрос по окончании таймера плюс как-то упорядочить обращение к объекту с сообщениями вот и ломаю голову, как же это сделать |
Cache,
основные кейзы ООП -- это наследование полиморфизм и инкапсуляция. Это средство проектирования, совместного, повторного использования кода, средство метапрограммирования. В твоем же случае, абсолютно похрену, как ты обработаешь ответ, со свитчем или без него, зря ты мучаешься. Использовать ООП ради самого ООП не нужно. Хотя, в контексте освоения механизмов, может это и будет для тебя полезно, просто для отработки навыков. |
protoquest,
ясн, спасибо |
Cache,
хотя, если я правильно тебя понял, то что ты говоришь, можно реализовать в объектном стиле, только не так как ты задумал, а как-то вот так
var request = {
KEY_VALUE: function(){alert(1)},
KEY_VALUE_SUBVALUE: function(){alert(2)},
handler: function(string){
this[string]()
}
}
request.handler("KEY_VALUE")
это замена свитч |
protoquest,
спасибо, подумаю над таким решением |
разве что, подобный подход, слишком упрощенный, т.к. showMsg() это не просто вызов alert(), но и выполнение некоторых операций, связанных с данным событием, и не всем событиям - требуется именно эта функция, по этому и требовалась ссылка именно на функцию, т.е. чтобы в зависимости от KEY - можно было бы указать обработчик (функцию) ..... как-то так
|
Цитата:
|
Цитата:
|
protoquest,
спасибо, я понял, буду разбираться.. с ООП, действительно - ступор какой-то с одной стороны, вроде бы - понятно, с другой - ни фига не получается=) |
protoquest,
вариант приведенного вами объекта - действительно прост и хорош,но к примеру, я хочу универсальности (или проблем на свою голову=) возьмем к примеру вариант, когда нет нужного ключа в массиве получим ошибку, либо нужно как-то вызвать функцию, для исключений... но опять же - она может быть не универсальна, например, часть ответов, по умолчанию требуют просто ожидания события и это можно определить из ключа в названии: Цитата:
NO_VALUE где VALUE - какое-то значение NO_xxxx - вне зависимости от VALUE - требует вызова определенной функции если при этом - VALUE нет в нашем объекте, но есть NO - можем вызвать функцию без параметров или с параметром по умолчанию если же ключ: BAD_VALUE то в не зависимости от VALUE (т.е. если данного значения нет во вложенном объекте BAD) мы можем вызвать функцию, ассоциированную с ключом BAD, если же есть, то соответственно, с параметрами взятыми из obj.BAD.VALUE надеюсь понятно обрисовал то, чего я хочу добиться.. теперь с кодом...: застрял на попытке вызова функции (опять таки =) потому что пытаюсь вызвать функцию по принципу подстановки ключей: test_obj['KEY']['VALUE'].func(obj['KEY']['VALUE'].metod) к примеру: r - возврат значения от сервера test_obj - объект с вариантами действий show - тестовая функция, которую нужно вызвать
var test_obj={
access:{
retry:{
get:{
metd: 500,
func: show
}
},
ready:{
metd: 300,
func: show
},
cancel:{
metd: 300,
func: show
}
},
no:{
service:{
metd:'параметры функции',
func:otherFunc
}
}
};
// входные данные
var r='ACCESS_RETRY_GET:1212:123654';
// обработка
// преобразуем ответ в массив
r=r.toLowerCase().split('_');
r=r.concat(r.pop().split(':'));
alert(r); // массив со значниями
print_r(r); // структура массива/объекта
r=callFunc(test_obj,r);
print_r(r); //for test
r.func(r.metd); // <= вызов вложенной функции
// функции
function show(s){
//alert(this);
alert(s);
};
function otherFunc(){
return this;
};
function callFunc(obj, arr, i){
var i=i||0;
print_r(obj); // for test
if(arr[i]&&!/\d+/.test(arr[i])){
alert(i+' '+arr[i]) // for test
obj=callFunc(obj[arr[i]],arr,++i);
};
return obj;
};
function print_r(variable, deep, index) { // temporary utils
if (variable===null) {var variable = 'null';}
if (deep===undefined) {var deep = 0;}
if (index===undefined) {var index = '';} else {index+=': ';}
var mes = ''; var i = 0; var pre = '\n';
while (i<deep) {pre+='\t'; i++;}
if (variable && variable.nodeType!=undefined) {
mes+=pre+index+'DOM node'+((variable.nodeType==1)? (' <'+variable.tagName+'>'): '');
}else if (typeof(variable)=='object') {
mes+=pre+index+' {';
for(index in variable) {
if (!variable.hasOwnProperty(index)){continue};
mes+=print_r(variable[index], (deep+1), index);
}
mes+=pre+'}';
} else {
mes+=pre+index+variable;
}
if (!deep){alert(mes);}
return mes;
};
судя по выводу print_r() из-за того, что в r попадает весь объект, вместо obj.access.retry.get исправил нужен совет, как лучше реализовать и стоит ли лезть в подобные дебри, если стоит то как вызвать в данной ситуации - функцию и параметры из объекта но вопрос остался, как сделать вызов функции по умолчанию, для тех объектов, которых нет в основном объекте например, пришел ответ от сервера: NO_PAGE в test_obj - есть объект NO но нет объекта PAGE, как в данном случае наиболее правильно присвоить нужную функцию - всему объекту NO предполагаю - что так:
...
no:{
service:{
....
},
metd:'параметры по умолчанию для NO',
func:'funcForNoObj'
}
...
но вот как ее правильно вызвать при таком коде (код выше) |
Цитата:
request: {
special: {
SPECIAL_ONE: function(){alert(1)},
SPECIAL_TWO: function(){alert(2)}
},
casual: {
ONE: function(){alert(2)},
TWO: function(){alert(4)}
},
errors: {
ERR_one: function(){alert(100)}
}
handler: function(key){
if(key in this.casual) return this.casual[key]()
if(key in this.special) return this.special[key]()
if(key in this.errors) return this.errors[key]()
throw new Error("WTF?")
}
}
|
Цитата:
А вообще, ты несколько искажаешь смысл. Основной профит не в этом, а в том, что мы можем наследовать функциональность, и расширять ее, не трогая базовый код, и в то же время, можем изменить базовый код, и изменения будут распространяться на все дочерние объекты |
Цитата:
еще бы понять - как=) до этого, работал, в основном, без ООП, да и опыта не так много, так что, для меня, пока что, подобная модель - темный лес... вот и задаю, порой, глупые вопросы), до решения которых, самому понимания не хватило поэкспериментировал, да, интересный вариант, спасибо за науку!
request={
special: {
SPECIAL_ONE: function(){alert(1)},
SPECIAL_TWO: function(){alert(2)}
},
casual: {
ONE: function(){alert(2)},
TWO: function(){alert(4)}
},
errors: {
ERR_one: function(){alert(100)}
},
handler: function(key){
if(key in this.casual) return this.casual[key]();
if(key in this.special) return this.special[key]();
if(key in this.errors) return this.errors[key]();
throw new Error("WTF?");
}
};
request.handler('SPECIAL_ONE');
request.handler('SPECIAL_the');
|
| Часовой пояс GMT +3, время: 10:30. |