Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Доступ к свойству внутри метода. (https://javascript.ru/forum/misc/30887-dostup-k-svojjstvu-vnutri-metoda.html)

LittlePony 19.08.2012 11:49

Доступ к свойству внутри метода.
 
Здравствуйте.
Вопрос: что я не так делаю?
Кусочек кода, содержащий только значимое для вопроса:
var Paradise = {
	state: "inactive",
	paradiseLost: function(){
		function AddActiveMarker(index,obj){
			console.log(obj.state)
		}
		AddActiveMarker(0,this)
	}
}

свойство state успешно меняется другой функцией.
Значение этого свойства нужно использовать в функции AddActiveMarker().
Внутри функции paradiseLost() это свойство читается нормально, но во вложенную функцию передать не могу, получаю undefined.
Где чего недопонимаю?
Заранее спасибо.

bot87 19.08.2012 12:00

var Paradise = {
    state: "inactive",
    paradiseLost: function(){
        function AddActiveMarker(index,obj){
           alert(obj.state)
        }
        AddActiveMarker(0,this)
    }
}
Paradise.state=90;
Paradise.paradiseLost()//90

LittlePony 19.08.2012 12:26

bot87, спасибо за ответ.
То есть, код корректен и всё должно работать?
Тем не менее у меня сейчас в консоль валится вот такая ошибка: Uncaught TypeError: Cannot read property 'state' of undefined.
Может быть в мою выдержку из кода не попало что-то существенное. Только учусь, ещё могу даже не понимать, где может быть ошибка.
Вот код объекта полностью:
var Paradise = Backbone.View.extend({
	el: $("#paradise"),
	model: appState,
	state: "inactive",
	animateDuration: 400,
	animateDelay: 400,
	initialize: function(){
		this.model.bind('change:frame', this.onFrameChange, this)
	},
	onFrameChange: function(){
		var cFrame = this.model.get("frame")
		switch (true) {
			case (cFrame>15 && cFrame<25):
				var ff = (25-cFrame)/20*Math.PI
				$(this.el).css({opacity:Math.cos(ff)}).show()
				break
			case(cFrame>48 && cFrame<56):
				var ff = (cFrame-48)/16*Math.PI
				$(this.el).css({opacity:Math.cos(ff)}).show()
				break
			case(cFrame>=25 && cFrame<=48):
				$(this.el).css({opacity:1}).show()
				if(cFrame>=30 && this.state=="inactive"){
					this.state="boom"
					this.paradiseBoom()
				}else if(cFrame<30 && this.state=="boom"){
					this.paradiseLost()
					this.state="inactive"
				}
				break
			default:
				$(this.el).hide()
				this.paradiseLost()
				this.state="inactive"
		}
	},
	paradiseBoom: function(){
		var $happiness = $(this.el).children("li")
		var animateDuration = this.animateDuration
		var animateDelay = this.animateDelay
		function AddActiveMarker(index,obj){
			var $cHappiness = $happiness.eq(index)
			if($cHappiness.size()==1){
				$("#eden").show()
				switch(index){
					case 0:
						$("#tree")
							.css({opacity:0,display:"block"})
							.animate({opacity:1},{duration:animateDuration})
						break
					case 1:
						$("#mrpostman")
							.css({opacity:0,display:"block"})
							.animate({opacity:1},{duration:animateDuration})
						break
					case 2:
						$("#bench")
							.css({opacity:0,display:"block"})
							.animate({opacity:1},{duration:animateDuration})
						break
				}
				$("<span class=activemarker />")
					.css({opacity:0})
					.appendTo($cHappiness).animate({opacity:1},{duration:animateDuration,complete:function(){
						if(obj.state=="boom") setTimeout(function(){AddActiveMarker(index+1,obj)},animateDelay)
					}})
			}
		}
		AddActiveMarker(0,this)
	},
	paradiseLost: function(){
		$(this.el).children("li").children("span.activemarker").remove()
		$("#eden").animate({opacity:0},{duration:400,complete:function(){
			$(this).hide().css({opacity:1})
			$("#eden>*").hide()
		}})
	}
})
var paradise = new Paradise()

В консоли ошибка указывает на эту строку: if(obj.state=="boom") setTimeout(function(){AddActiveMarker(index+1,obj) },animateDelay)

melky 19.08.2012 13:03

Цитата:

Сообщение от LittlePony
Где чего недопонимаю?

http://learn.javascript.ru/this#вы...функции

this становится window - если вкратце.

nerv_ 19.08.2012 13:16

LittlePony, для начала вам надо понять:
1. что такое this (если уж совсем по простому),
2. как передавать нужный вам this

var Paradise = {
	state: "inactive",
	paradiseLost: method
};

function method() {
	alert( this === Paradise );
}

Paradise.paradiseLost();	// true
method.call( Paradise )		// true

LittlePony 19.08.2012 20:35

Цитата:

Сообщение от melky (Сообщение 198737)
http://learn.javascript.ru/this#вы...функции

this становится window - если вкратце.

Большое спасибо за эту ссылку на статью. Статья открыла глаза на многое, бывшее до этого непонятным.

Однако нет, this не становится window. Если сделать
console.log(this)
, то в консоли пишется:
Код:

d
$el: p.fn.p.init[1]
cid: "view4"
el: HTMLUListElement
options: Object
state: "boom"
__proto__: x

что, собственно, и ожидалось. Свойство state у этого объекта есть и правильно читается. Но если внутри функции AddActiveMarker() написать
console.log(obj)
, то в консоли пишется:
Код:

Uncaught TypeError: Cannot read property 'state' of undefined init.js:219
Backbone.View.extend.paradiseBoom.$.css.appendTo.animate.complete init.js:219
p.speed.d.complete jquery.js:2
p.Callbacks.k jquery.js:2
p.Callbacks.l.fireWith jquery.js:2
i jquery.js:2
p.fx.tick

и вот это уже мне совершенно непонятно.

nerv_ 19.08.2012 20:54

Цитата:

Сообщение от LittlePony
Однако нет, this не становится window. Если сделать

внутри обработчика события, повешанного на элемент DOM c помощью квери, this ссылается на этот элемент.

AddActiveMarker.call( Paradise, 0, Paradise );

LittlePony 19.08.2012 21:33

Цитата:

Сообщение от nerv_ (Сообщение 198830)
внутри обработчика события, повешанного на элемент DOM c помощью квери, this ссылается на этот элемент.

AddActiveMarker.call( Paradise, 0, Paradise );

nerv_, большое спасибо на внимание и помощь. Но пока результат тот же.
А ещё мне бы хотелось не только добиться работоспособности, но и понять, как это всё работает.
Так вот, если я правильно понимаю, то между записями
AddActiveMarker.call( Paradise, 0, Paradise );
и
AddActiveMarker( 0, Paradise );
разница только та, что в первом случае мы явно указываем, что будет скрываться под this внутри этой функции при таком вызове. Но нигде внутри этой функции this не используется. Тогда в чём смысл такой замены?

nerv_ 19.08.2012 21:51

Цитата:

Сообщение от LittlePony
Тогда в чём смысл такой замены?

мне показалось по первому примеру смысл был.

Сейчас еще раз посмотрел твой код. Як у тебя там все наворочено и точек с запятыми не хватает )

Смотри, если проблема здесь,
AddActiveMarker(0,this)

ищи, что такое этот this и откуда он передается

Еще есть "секретный" способ сделать правильный this
function Constructor() {
	var self = this;
	
	self.method = function() { };
}

var cat = new Constructor();

вроде твой случай

LittlePony 19.08.2012 22:01

Цитата:

Сообщение от nerv_ (Сообщение 198847)
мне показалось по первому примеру смысл был.

Сейчас еще раз посмотрел твой код. Як у тебя там все наворочено и точек с запятыми не хватает )

Это разве наворочено? :) Это только малая часть кода, только один из объектов. Если интересно, могу потом, когда будет готово, показать результат. А точек с запятыми где не хватает?


Цитата:

Сообщение от nerv_ (Сообщение 198847)
Смотри, если проблема здесь,
AddActiveMarker(0,this)

ищи, что такое этот this и откуда он передается

Нет, проблема не здесь, проверено. Если прямо перед этим вызовом функции поставить console.log(this), то выводится то, что и ожидается.
Но если даже сразу в этой функции первой строкой поставить вывод того, что в неё передалось, то выводится совершенно неожиданный результат.


Цитата:

Сообщение от nerv_ (Сообщение 198847)
Еще есть секретный способ сделать правильный this
function Constructor() {
	var self = this;
	
	self.method = function() { };
}

var cat = new Constructor();

вроде твой случай

А вот это непонятно. Можешь объяснить или послать, где почитать о таком?


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