Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   своё замыкание каждому объекту. (https://javascript.ru/forum/misc/12103-svojo-zamykanie-kazhdomu-obektu.html)

Kolyaj 01.10.2010 13:45

А как тогда присвоить undefined? Этакое обнуление свойства.

Sweet 01.10.2010 13:59

Обnullять можно присваивая null:) Но по уму тут нужно не "обнулять" значение, а выдергивать весь объект из массива storage: если он пустой (undefined), то и незачем по нему пробегать в цикле for.

cainrus 02.10.2010 05:17

я в Вашем примере кода, попробовал не заталкивать с помощью "push" значения в массив, а использовать storage как объект, в который по ключу ставить значения:
storage[this] = newValue;


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

Sweet 02.10.2010 10:26

cainrus, покажи, пожалуйста, рабочий пример:)
Вообще, ключ в объекте, если кто не в курсе, - строка. Так что же ввело в заблуждение?
var object = {}, innerObject = {};
object[innerObject] = {prop: 'value'};
alert(object[innerObject].prop); // value

var string = innerObject.toString(); // [object Object]
alert(object[string].prop); // value

// А вот, что происходит на самом деле:
alert(object['[object Object]'].prop); // value

Sweet 02.10.2010 11:34

Кстати, вариант storage[this] = newValue; вполне возможен. Правда, придется залезть не только в Object.prototype, но и в метод toString. Учтите, Kolyaj не даст соврать, при этом бог убьет не только котенка, но и щеночка. Поэтому вариант с циклом мне более симпатичен:)
Object.prototype.key = (function(){
  var storage = {}, count = 0;
  return function(value){
    if(this.toString()=='[object Object]') this.toString=(function(){
      var string = 'obj'+count;
      count++;
      return function(){return string;};
    }());
    if(arguments.length!=0){
      storage[this] = value;
      return value;
    };
    return storage[this];
  };
}());

var FirstObject = {a:1}, SecondObject = {b:2};
FirstObject.key(100);
SecondObject.key(999);

alert([FirstObject.key(), SecondObject.key()]);

cainrus 02.10.2010 17:11

Да, я обнаружил что мой код не работает правильно, когда посмотрел метод toString(). Если есть два массива с одинаковым наполнением, то ключ хранения между ними будет общий, а если хранить объекты в массиве, тогда баг проявится при одинаковом количестве объектов в массиве.

// Extending Array Object
Array.prototype.key = (function(){
	  var storage = [];
	  return function(key){
              
		if ( typeof(key) !== "undefined" ) {
		// Add positive number or null, if key presents, and return self instance.
			key = parseInt(key);
                        // If key is invalid or out of range, then it should be null.
			if (key < 0 || key > this.length - 1 || isNaN(key)) key = null;
			storage[this] = key;
			return this;
		} else {
		// Return key
			key = storage[this];
			// If key is undefined, then it should be null.
			if (typeof(key) === "undefined") key = null;
			return key;
		}
		// Get value; if value is not defined, then set it to null.
		if (typeof(value = storage[this]) === "undefined") value = null;

		// Return index of array or null if array is empty
		return value;
	  }
	}());


// Let's test two new arrays
SomeArray = [1,2,3,4,5,6,7,8,9];
AnotherArray = ['a','b','c','d','e','f','g'];
BonusArray = ['a','b','c','d','e','f','g'];
// key method should return key index
alert('SomeArray key = '+SomeArray.key()); //null, there is no index yet
SomeArray.key(2); // set first array index to 2
AnotherArray.key(5); // set second array index to 5
alert('SomeArray key = '+SomeArray.key()); // 2 !
alert('AnotherArray key = '+AnotherArray.key()); // 5 !
alert('BonusArray key = '+BonusArray.key()); // 5 ! but it should not..


Перепишу фишку, используя первоначальный способ с циклом, раз нет других способов :)

Sweet 02.10.2010 19:05

Не, ты явно не понял сути конструкции типа storage[this]!!!
Вот смотри, почему у тебя возникает "баг" (это не баг, просто функция криво написана):
Когда ключ - объект, он приводится к строке методом toString(). У массива в таком случае возвращается строка со значениями через запятую. Так вот что у тебя происходит.
alert('SomeArray key = '+SomeArray.key());
//функция смотрит storage['1,2,3,4,5,6,7,8,9']. Его нет.

SomeArray.key(2);
//функция устанавливает storage['1,2,3,4,5,6,7,8,9'] = 2

AnotherArray.key(5);
//устанавливает storage['a,b,c,d,e,f,g'] = 5

alert('SomeArray key = '+SomeArray.key());
//смотрим storage['1,2,3,4,5,6,7,8,9']. Там значение 2

alert('AnotherArray key = '+AnotherArray.key());
//смотрим storage['a,b,c,d,e,f,g']. Там значение 5

alert('BonusArray key = '+BonusArray.key());
//BonusArray.toString() = 'a,b,c,d,e,f,g'.
//смотрим storage['a,b,c,d,e,f,g']. Там значение 5
//Вот и весь "баг"

cainrus 03.10.2010 00:13

да, я понял это когда прочитал про функцию toString.

Сначала ошибочно посчитал(не проверил), что this должен преобразоваться в [Object Object](когда я его использую в качестве индекса массива), но раз ошибок не возникало(не проверял одинаково наполненные массивы), посчитал что действительно объекты помещаются в индексы(вот глупость!).
Если бы я наполнял массивы объектами, то выявил бы ошибку ещё раньше, надеюсь понятно почему :-) но, спасибо за твоё время.

tenshi 04.10.2010 22:42

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

tenshi 04.10.2010 22:44

Цитата:

Сообщение от cainrus (Сообщение 72559)
Sweet:
Удивляюсь как вы до этого дошли. Работает так как требовалось. Первоначально я всего лишь хотел реализовать функционал для массива как в php: next, prev, current, end, reset, key. Всё застопорилось, когда я обнаружил, что внутренний указатель во всех массивах везде одинаков.

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


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