Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   И снова контекст в setTimeout (https://javascript.ru/forum/misc/33864-i-snova-kontekst-v-settimeout.html)

cib 11.12.2012 21:29

И снова контекст в setTimeout
 
Доброго времени суток!
Нужно создать объект с приватными и публичными свойствами и методами так, чтобы все части объекта могли работать друг с другом, в т.ч. по таймаутам и интервалам без ограничений видимости, контекста и т.д., ну а внешние объекты - согласно уровню доступа. Наследников не будет.
Делаю так:

function obj() {
  privateField1;
  var privateField2;
  this.publicField;

  function privateMethod(){
    if( privateField1 == ... ) { //do something }
    if( privateField2 == ... ) { //do something else }
    if( this.publicField == ... ) { //do something else else :) }
  },

  this.publicMethod1 = function() {
      var self = this;
      setTimeout( function(){ self.privateMethod(); }, interval );
  },

  this.publicMethod2 = function() {
      var self = this;
      setTimeout( function(){ privateMethod.call( self ); }, interval );
  }
}

document.MyObj = new obj();
document.MyObj.publicMethod1();
document.MyObj.publicMethod2();


И получается так, что внутри приватного метода несмотря на передачу контекста значения полей не соответствуют тому, что лежит в экземпляре объекта. При разных манипуляциях способ вызова может начать ругать и на "privateMethod() is not a function".
privateField1 вообще становится частью объекта window и его модификация в разных контекстах приводит к тому, что одновременно существуют window.privateField1, MyObj.proivateField1 и this.privateField1 с разными значениями в зависимости от контекста.
Если все поля и методы сделать публичными, то первый метод работает нормально, но теряется управление уровнем доступа для внешних объектов.

Подскажите, в каком месте у меня затуп и ЧЯДНТ?

Hoshinokoe 11.12.2012 21:54

cib,

В этой ветке уже все разобрали.

cib 11.12.2012 22:01

Цитата:

Сообщение от Hoshinokoe (Сообщение 220866)
cib,

В этой ветке уже все разобрали.

Вы видимо невнимательно прочитали вопрос. У меня нет проблем с вызовом чего-то в таймере или интервале, у меня проблема с контекстом выполнения и областью видимости уже при выполнении вызванной функции. А в указанном Вами посте (который я уже прочитал перед тем как создавать свой) обсуждаются способы указания первого параметра таймера (в скобках ,в анонимке и т.п.), а в конце ссылка на статью по общей информации по областям видимости.
Если я не прав - ткните меня носом в недопонятые мною сообщения в том посте.

dmitriymar 11.12.2012 22:10

Цитата:

Сообщение от cib
может начать ругать и на "privateMethod() is not a function".

чего бы это? а ?
Цитата:

Сообщение от cib
function privateMethod(){
if( privateField1 == ... ) { //do something }
if( privateField2 == ... ) { //do something else }
if( this.publicField == ... ) { //do something else else :) }
},

как функции объявлять знаете? а различия синтаксиса в литерале и в конструкторе?
Цитата:

Сообщение от cib
privateField1 вообще становится частью объекта window и его модификация в разных контекстах приводит к тому, что одновременно существуют window.privateField1, MyObj.proivateField1 и this.privateField1

тоже странно...
как вызывать конструктор объекта знаете?

tropiko 11.12.2012 22:14

function obj(){
		var self = this;
		
		var privateField = "I'm privateField value";
		var privateMethod = function(){
			alert('Whoo!');
		}
		
		self.publicField = "I'm publicField value";
		self.publicMethod = function(){
			return privateField;
		}
		self.publicMethod2 = function(){
			setTimeout(
				function(){
					privateMethod.call(self);
				},
				1000
			);
		}
	}

	var obj = new obj();

	console.log(obj.privateField); //Undefined
	console.log(obj.privateMethod()); //TypeError

	console.log(obj.publicField);
	console.log(obj.publicMethod());
	obj.publicMethod2();

cib 11.12.2012 22:17

Цитата:

Сообщение от dmitriymar
чего бы это? а ?

ругается "при разных манипуляциях"... это я к тому, что пробовал по-разному

Цитата:

Сообщение от dmitriymar
как функции объявлять знаете? а различия синтаксиса в литерале и в конструкторе?

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

Hoshinokoe 11.12.2012 22:38

Цитата:

Сообщение от Hoshinokoe (Сообщение 220866)
cib,

В этой ветке уже все разобрали.

В указанной ветке была замечательная ссылка на учебник, в котором описан контекст выполнения функция setTimeout c примерами.

nerv_ 11.12.2012 22:38

реально это тема минимум раз в день создается/высплывает или мне кажется? :blink:

cib 11.12.2012 23:01

Я как Винни-Пух - "ничего не понимаю".
Скопипастил пример tropiko, внес туда нужные мне исправления - всё работает. И работает так, как не работало в проекте.
Опять вношу изменения в проект (1 в 1 нерабочий вариант из-за которого пост создал) и вуаля! Всё работает. Вот как так?
Одного не пойму - почему "this.IncomingQueue is undefined", а "this.EngineRunning == true" ?

function obj() {
	var EngineRunning = true;
	var IncomingQueue = [ 'element1', 'element2' ];
	//и другие свойства

	this.StartEngine =
		function() { 
			var self = this;
			this.ThreadExecID = 
				setTimeout( 
						   function(){ 
						   		setInterval( 
											function() {
												ThreadExec.call(self); 
											}, 
											self.ExecInterval
											); 
							},
							self.InterThreadInterval * 2 
						);
		},
	var ThreadExec =
		function(){
			if( !this.EngineRunning ) return;
			if( this.IncomingQueue.length > 0 ) {
				//..............
			}
		}
}
var obj = new obj();
obj.StartEngine();

cib 11.12.2012 23:32

всё, считаю тему закрытой.
отдельное спасибо tropiko за "эффект присутствия"


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