Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   объекты и работа с ними (https://javascript.ru/forum/misc/62277-obekty-i-rabota-s-nimi.html)

Cache 02.04.2016 18:35

объекты и работа с ними
 
просьба сильно не пинать, а объяснить и/или дать ссылку на хороших мануал, только пытаюсь разобраться с ООП
есть объект имеющий древовидную структуру:
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) - вообще не получилось, видимо, как-то не правильно создаю указатель

Cache 02.04.2016 19:40

как изменить имя - вроде бы разобрался (в принципе-то, банально), но получилось только вне объекта:
obj.showF=obj.func.showF;

а хотелось бы - изнутри, но конструкция вида:
obj.showF: obj.func.showF

возвращает ошибку

destus 02.04.2016 21:21

Цитата:

как переделать этот код, чтобы:
можно было обратиться сразу к внутреннемому объекту (например, к func) и в параметрах, указывать не полный идентификатор объекта (obj.func.msg3), а только последний (msg3), т.е. как-то так:
obj.showF('msg3')
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');

protoquest 02.04.2016 21:27

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")

так штоле?

Cache 02.04.2016 22:05

protoquest, да, вроде бы так, спасибо

Cache 02.04.2016 22:07

protoquest,
а возможно - без указания this.func[m] в функции? т.е. как-то так:
function showE(m){
    alert(this[m])
}

?
а в оптимале, чтобы была вообще одна функция, а в зависимости от места вызова применялся - нужный контекст
т.е. если вызвано из объекта obj.func то и контекст брался этого объекта

protoquest 02.04.2016 22:11

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")

Cache 02.04.2016 22:15

destus,
спасибо, не увидел ваш ответ сразу - то что нужно

Cache 02.04.2016 22:18

Цитата:

Сообщение от protoquest
У Вас на самом деле нет четкого понимания, чего Вы на самом деле хотите.

да, это действительно так, сейчас экспериментирую, пытаясь понять, как лучше сделать и как именно это можно использовать, потому что - данный способ - легко заменяется
showMsg(obj.func.msg3)
вот и пытаюсь понять плюсы и минусы метода, и его удобства

Cache 02.04.2016 22:22

Цитата:

Сообщение от protoquest
хотя, возможно, через жопу сделать, используя bind, но не нужно

а можно по конкретней, почему через "жопу"?

protoquest 02.04.2016 22:22

Cache,
Вас вообще не в ту степь прет. это почти то же самое, что
obj.showF = function(m){alert(obj.func[m])}

protoquest 02.04.2016 22:25

Цитата:

Сообщение от Cache
а можно по конкретней, почему через "жопу"?

ладно, дело ваше, может найдется задача, где это Вам действительно понадобится.

Cache 02.04.2016 22:40

protoquest,
как же сказал выше - только учусь, и ООП - для меня темный лес...
Суть задачи, хочу обойтись без switch при обработке ответа от сервера, имеющего вид:
Код:

KEY_VALUE
или
KEY_VALUE_SUBVALUE

где KEY - критичность сообщения
VALUE и SUBVALUE - подробности
например:
ERROR_SQL или BAD_KEY

в зависимости от этого, хочу вызывать нужную функцию, например, при BAD_KEY нужно вызвать showMsg() с сообщением об ошибке введенного ключа, аналогично при других ошибках с ключом BAD_
а при ERROR_SQL - нужно запустить функцию-таймер, которая повторит запрос по окончании таймера

плюс как-то упорядочить обращение к объекту с сообщениями

вот и ломаю голову, как же это сделать

protoquest 02.04.2016 22:48

Cache,
основные кейзы ООП -- это наследование полиморфизм и инкапсуляция. Это средство проектирования, совместного, повторного использования кода, средство метапрограммирования. В твоем же случае, абсолютно похрену, как ты обработаешь ответ, со свитчем или без него, зря ты мучаешься. Использовать ООП ради самого ООП не нужно. Хотя, в контексте освоения механизмов, может это и будет для тебя полезно, просто для отработки навыков.

Cache 02.04.2016 23:00

protoquest,
ясн, спасибо

protoquest 02.04.2016 23:00

Cache,
хотя, если я правильно тебя понял, то что ты говоришь, можно реализовать в объектном стиле, только не так как ты задумал, а как-то вот так
var request = {
  KEY_VALUE: function(){alert(1)},
  KEY_VALUE_SUBVALUE: function(){alert(2)},
  handler: function(string){
    this[string]()
  }
}

request.handler("KEY_VALUE")

это замена свитч

Cache 02.04.2016 23:14

protoquest,
спасибо, подумаю над таким решением

Cache 02.04.2016 23:23

разве что, подобный подход, слишком упрощенный, т.к. showMsg() это не просто вызов alert(), но и выполнение некоторых операций, связанных с данным событием, и не всем событиям - требуется именно эта функция, по этому и требовалась ссылка именно на функцию, т.е. чтобы в зависимости от KEY - можно было бы указать обработчик (функцию) ..... как-то так

protoquest 03.04.2016 10:33

Цитата:

Сообщение от Cache
т.е. чтобы в зависимости от KEY - можно было бы указать обработчик (функцию) ..... как-то так

то что я Вам привел как раз это и делает

protoquest 03.04.2016 10:38

Цитата:

Сообщение от Cache
это не просто вызов alert(), но и выполнение некоторых операций, связанных с данным событием

туда вместо алерта можно впихнуть все что угодно. У тебя действительно ступор какой-то с ООП.

Cache 03.04.2016 15:49

protoquest,
спасибо, я понял, буду разбираться.. с ООП, действительно - ступор какой-то с одной стороны, вроде бы - понятно, с другой - ни фига не получается=)

Cache 03.04.2016 21:59

protoquest,
вариант приведенного вами объекта - действительно прост и хорош,но к примеру, я хочу универсальности (или проблем на свою голову=)

возьмем к примеру вариант, когда нет нужного ключа в массиве
получим ошибку, либо нужно как-то вызвать функцию, для исключений...
но опять же - она может быть не универсальна, например, часть ответов, по умолчанию требуют просто ожидания события и это можно определить из ключа в названии:
Цитата:

KEY_VALUE_SUBVALUE или KEY_VALUE
например, если ключ:
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;
};

в строке 19 - вызов функции и метода, который не работает
судя по выводу print_r() из-за того, что в r попадает весь объект, вместо obj.access.retry.get

исправил

нужен совет, как лучше реализовать и стоит ли лезть в подобные дебри, если стоит то как вызвать в данной ситуации - функцию и параметры из объекта

но вопрос остался, как сделать вызов функции по умолчанию, для тех объектов, которых нет в основном объекте
например, пришел ответ от сервера:
NO_PAGE
в test_obj - есть объект NO но нет объекта PAGE, как в данном случае наиболее правильно присвоить нужную функцию - всему объекту NO
предполагаю - что так:
...
no:{
    service:{
        ....
    },
    metd:'параметры по умолчанию для NO',
    func:'funcForNoObj'
}
...

но вот как ее правильно вызвать при таком коде (код выше)

protoquest 03.04.2016 23:33

Цитата:

Сообщение от Cache
это можно определить из ключа в названии:

ну так и диспетчеризуй их по названию
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?")
   }
}

protoquest 03.04.2016 23:44

Цитата:

Сообщение от Cache
надеюсь понятно обрисовал то, чего я хочу добиться

честно говоря, не особо понятно, у меня голова забита, мне не до твоих сложных правил, но суть в том, что любой ключ можно разбить на части, и диспетчирезовать его как хочешь.

А вообще, ты несколько искажаешь смысл. Основной профит не в этом, а в том, что мы можем наследовать функциональность, и расширять ее, не трогая базовый код, и в то же время, можем изменить базовый код, и изменения будут распространяться на все дочерние объекты

Cache 04.04.2016 00:49

Цитата:

Сообщение от protoquest
мы можем наследовать функциональность, и расширять ее, не трогая базовый код, и в то же время, можем изменить базовый код, и изменения будут распространяться на все дочерние объекты

эрм.. ну ты/вы загнул/выразился... =) хоть на цитаты разбирай ))
еще бы понять - как=) до этого, работал, в основном, без ООП, да и опыта не так много, так что, для меня, пока что, подобная модель - темный лес... вот и задаю, порой, глупые вопросы), до решения которых, самому понимания не хватило

поэкспериментировал, да, интересный вариант, спасибо за науку!
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, время: 23:56.