Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   User Objects... (https://javascript.ru/forum/misc/1158-user-objects.html)

claster 15.04.2008 20:05

User Objects...
 
Добрый вечер, господа, требуется помощь... есть код:
window.onload=function(){

div=document.createElement("DIV")
div.style.cssText="width:100px;height:100px;border :1px solid blue;"
document.body.appendChild(div);
user_obj=new UserObject();
user_obj.bg.call(div); // $1

}
function UserObject(){
this.color="blue";

}
UserObject.prototype.bg=function(){

//$2
this.style.backgroundColor="red";
}
Как в методе bg (отмечено $2) достучаться до свойства color этого же объекта если this уже ссылается на HTML элемент div, смотри выше отмечено $1?

vandy 16.04.2008 10:40

Как вариант:
div=document.createElement("DIV")
div.style.cssText="width:100px;height:100px;border :1px solid blue;"
document.body.appendChild(div);
user_obj=new UserObject();
user_obj.bg.call(div);

function UserObject(){
  var me = this;
  me.color="blue";
  me.bg=function(){
   this.style.backgroundColor=me.color; 
  }
}

claster 16.04.2008 15:00

vandy, спасибо за ответ, такой вариант я рассматривал, но у него есть один недостаток, локальная переменная me не видна в методах определенных через prototype :(
Есть еще идеи?

vandy 16.04.2008 15:07

Конечно не работает, Я же написал - "как вариант". И мой пример работает без prototype.
Вопрос - а почему вы используете prototype? Чем не устраивает вариант созданиея объектов, как в моем примере.

Kolyaj 16.04.2008 15:15

claster, измените логику программы. К примеру, передавайте div в качестве аргумента функции bg, а то фигня какая-то получается.

Цитата:

Сообщение от vandy
Чем не устраивает вариант созданиея объектов, как в моем примере.

В вашем примере для каждого создаваемого объекта будет создаваться свой набор методов, а при использовании prototype он (набор методов) будет один. Т.е. с prototype и быстрее и памяти меньше.

claster 16.04.2008 15:29

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

claster 16.04.2008 15:36

Kolyaj, дело не в конкретном примере, просто нужно разобраться и в таком подходе...

Kolyaj 16.04.2008 16:02

claster, так я про подход и говорю, херовый какой-то подход. Вы можете показать реальный пример, где такое может быть полезным?

Dmitry A. Soshnikov 16.04.2008 16:13

claster, вынеси определение bg выше вызова user_obj.bg.call(div);. А все дело в том, что функции могут объявляться как Statement и как Declaration.

Чтобы увидеть разницу, попробуй так:

a();// работает

function a() { 
  alert(1);
}


a();// не работает

var a = function() { 
  alert(1);
}


Поэтому вот это работает:

function UserObject() {
  this.color = 'blue';
  return true;
}

UserObject.prototype.bg = function() {
  this.style.backgroundColor = 'red';
  return true;
}

var div = document.createElement("DIV")
div.style.cssText = "width:100px;height:100px;border :1px solid blue;"
document.body.appendChild(div);
var user_obj = new UserObject();
user_obj.bg.call(div); // $1


И даже это работает (сам UserObject описан ниже всех, но он является декларацией, а не стейтментом):

UserObject.prototype.bg = function() {
  this.style.backgroundColor = 'red';
  return true;
}

var div = document.createElement("DIV")
div.style.cssText = "width:100px;height:100px;border :1px solid blue;"
document.body.appendChild(div);
var user_obj = new UserObject();
user_obj.bg.call(div); // $1

function UserObject() {
  this.color = 'blue';
  return true;
}


Но, в твоем случае - нет.

claster 16.04.2008 16:59

Видимо я не правильно поставил вопрос... я пытаюсь разобраться в объектном подходе, а именно: есть пользовательский объект с набором методов, некоторые методы используют родственные методы и свойства, как применить один или несколько методов к HTML элементу или группе без издержек т.е. копирования методов пользовательского объекта для каждого HTML элемента... как то так, уж простите в ООП я пока не силен.

claster 16.04.2008 17:46

Вроде как разобрался, пошел другим путем, вот коротенький примерчик, подскажите может есть и другие решения или я в корне не правильно мыслю?
window.onload=function(){
		for (var i = 0; i < 10; i++) {
			var box = new Box();
			box.append(document.body)
			box.styled();
			box.moveRandPos(500, 700);
			box.moveRandBacColor();
		}
	}
	function Box(element){
		this.box = element || this.create();
	}
	Box.prototype.create=function(){
		return document.createElement("DIV");
	}
	Box.prototype.append=function(to){
		return to.appendChild(this.box)
	}
	Box.prototype.styled=function(){
		this.box.style.cssText = "width:30px;height:30px;border:1px solid blue;position:absolute;"
		return this.box;
	}
	Box.prototype.randColor=function(){
		var sb = "0123456789abcdf";
		var color = "#";
		for(var i=0; i<6; i++){
			color += sb.charAt(Math.random()*15);
		}
		return color;
	}
	Box.prototype.randBacColor=function(){
		this.box.style.backgroundColor = this.randColor();
		return this.box;		
	}
	Box.prototype.moveRandBacColor=function(){
			var _this = this;
			function go()
			{
				_this.randBacColor();
				setTimeout(go,1000)
			}	
			go()
	}
	Box.prototype.randPos = function(max_top,max_left){
		
		this.box.style.top = parseInt(Math.random()*(max_top-1)) + "px";		
		this.box.style.left = parseInt(Math.random()*(max_left-1)) + "px";
	}		
	Box.prototype.moveRandPos=function(max_top,max_left){
			var _this = this;
			function go()
			{
				_this.randPos(max_top,max_left);
				setTimeout(go,1000)
			}	
			go()
	}

Dmitry A. Soshnikov 16.04.2008 18:09

claster, ?? я зря объяснял? ;) Или что-то было упущено? Или пример сильно отличался от твоего кода? =)

Kolyaj, не сбивай с толку человка =)

claster 16.04.2008 18:49

ds [.code], в первом подходе я так и не смог получить доступ к родственным методам и свойствам в нутри метода определенного через прототип...
function UserObject() {
	this.color = 'blue';
	var _this = this;
	return true;
}
 
UserObject.prototype.bg = function() {

  this.style.backgroundColor = this.color;
  //alert(this.color); - это undefined так как this уже ссылаеться на div 
  //alert(_this.color); - это not defined
  return true;
}

var div = document.createElement("DIV")
div.style.cssText = "width:100px;height:100px;border :1px solid blue;"
document.body.appendChild(div);
var user_obj = new UserObject();
user_obj.bg.call(div);


в коде есть комментарии...

поэтому зашел с другой стороны :)
вот теперь меня интересует, правильно ли я мыслил во второй раз?
если же есть выход в первом случае, с удовольствием готов узнать решение.

Dmitry A. Soshnikov 16.04.2008 21:34

claster, ууупс, да что ж такое-то! - опять я неправильно вопрос прочитал (мне причудилось, что у тебя там падает с ошибкой, а все из-за того, что я скопировал твой код без window.onload) - переутомление, наверно, прошу извинить =) Да, call и apply вызывают метод в контексте переданного объекта. В грубом приближении - просто подставиться нужная ссылка this (this будет правильно ссылаться - на нужный объект). А вот свойства color в твоем div'е нет. Поэтому, второй вариант (где div хранится отдельным свойством UserObject'a) правильней и подобных проблем не вызовит.

claster 17.04.2008 00:49

ds [.code], я рад что ты понял суть проблемы, по крайней мере спасибо что пытался помочь, за что респект, но первый вариант пока остается без решения...

Dmitry A. Soshnikov 17.04.2008 01:47

claster, а какое может быть решение при первой организации? Метод (и только метод!) вызывается в контексте нужного объекта. Означает это всего лишь то, что this в этот момент будет ссылаться на переданный объет. Это как будто у объекта "на пару секунд" (на время выполнения) появился свой такой же метод, как у родного объекта (которому принадлежит метод). Но свойстами объект будет оперировать своими, а не родного объекта. Поэтому, естественно, свойства color div не имеет и нельзя присвоить this.color. И поэтому оптимальной организацией является вторая, - где твой div хранится свойством объекта, и тогда до него можно достучаться в прототипе.

claster 17.04.2008 09:04

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

Dmitry A. Soshnikov 17.04.2008 12:13

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

нет, ну почему - если за "обходной маневр" посчитать, что UserObject работает только со свойствами конкретного объекта (или группы конкретных объектов со схожими свойствами), то вполне сработает и первый вариант (т.е. UserObject просто станет оберткой для методов объектов, вызванных call'ом или apply'ем)

Третьим вариантом может быть расширение самого объекта (div'a в твоем случае) таким методом (тогда можно будет вызвать твойDiv.bg(), хотя при первом варианте (при условии, что UserObject работает только со нужными свойствами) будет тратиться меньше памяти, поскольку вызывается всегда одна единственная функция в нужном контексте). Кстати, в FF и Opera можно расширить встроенные интерфейсы (например window.HTMLElement), от которого наследуются html-елементы и тогда также памяти сожрется меньше (тоже будет всего одна функция в прототипе) и также можно вызывать твойDiv.bg();

vandy 17.04.2008 18:47

Kolyaj,
Цитата:

В вашем примере для каждого создаваемого объекта будет создаваться свой набор методов, а при использовании prototype он (набор методов) будет один. Т.е. с prototype и быстрее и памяти меньше.
Поясните, пож.

claster 17.04.2008 19:44

Цитата:

Сообщение от ds [.code] (Сообщение 2020)
>Кстати, в FF и Opera можно расширить встроенные интерфейсы (например window.HTMLElement), от которого наследуются html-елементы и тогда также памяти сожрется меньше (тоже будет всего одна функция в прототипе) и также можно вызывать твойDiv.bg();

Мало того, в нормальных браузерах можно расширить Object и эти методы будут доступны для HTML элементов, но есть Ослик который естественно всегда был и останется стокилограммовой гирей привязанной к ноге девелоперов...
Спасибо за помощь!

Kolyaj 17.04.2008 20:26

vandy,
Пример 1:
function F(t) {
  this.t = t;
}
F.prototype = {
  m1: function() { alert(this.t) }
};
var f1 = new F(1);
var f2 = new F(2);


Пример 2:
function F(t) {
  this.t = t;
  this.m1 = function() {  alert(this.t); };
}
var f1 = new F(1);
var f2 = new F(2);

В первом примере свойства f1.m и f2.m указывают на одну и ту же функцию, а значит, памяти тратится меньше. Также во втором примере методы создаются непосредственно в конструкторе, что, разумеется, работает медленнее, чем в первом примере, где в конструкторе выполняется только присваивание t.

tenshi 18.04.2008 02:08

Цитата:

Сообщение от claster (Сообщение 2031)
Мало того, в нормальных браузерах можно расширить Object и эти методы будут доступны для HTML элементов, но есть Ослик который естественно всегда был и останется стокилограммовой гирей привязанной к ноге девелоперов...
Спасибо за помощь!

это решается специальной компонентой ;-)

.ня

vandy 18.04.2008 10:38

Kolyaj,
А есть какие-нибудь тесты/исследования про скорость и память в обоих случаях?

claster 18.04.2008 13:46

Цитата:

Сообщение от tenshi (Сообщение 2039)
это решается специальной компонентой ;-)

ссылку в студию... хотелось бы ознакомиться с сием чудом...

tenshi 18.04.2008 20:58

ссылку не дам, но рассказать как работает - могу.
на все элементы навешивается компонента, которая при инициализации лезет к нашему HTMLElement.prototype и примешивает его слоты.


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