Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   "расширить бы массив", или "расскажите как работают прототипы" (https://javascript.ru/forum/misc/40318-rasshirit-massiv-ili-rasskazhite-kak-rabotayut-prototipy.html)

weeklyTea 31.07.2013 15:05

"расширить бы массив", или "расскажите как работают прототипы"
 
Есть следующий код:
function newObj(){
}
newObj.prototype = Array.prototype;
tt = new newObj();
tt[0] = 11;
tt[1] = 22;
alert(tt.length); // пишет 0
alert(tt[0]); // пишет 11
alert(tt[1]); // пишет 22

tt.push(99);
alert(tt.length); // пишет 1
alert(tt[0]); // пишет 99
alert(tt[1]); // пишет 22


можете объяснить такое поведение? )

ksa 31.07.2013 15:30

Цитата:

Сообщение от weeklyTea
можете объяснить такое поведение?

Твой tt есть объект...

tt[0] = 11;

Изменеие/создание свойства объекта...

Но поскольку ты занаследовался от массива (это так же объект) - у тебя есть метод push()

tt.push(99);

Выполнилось создание элемента массива, изменилась длина

alert(tt.[0]); // пишет 99

Потому как имя свойства объекта "совпало" с первым элементом массива...

Что-то такое.

рони 31.07.2013 15:39

Цитата:

Сообщение от weeklyTea
tt.[0]

интересно как это может работать?

weeklyTea 31.07.2013 18:51

Цитата:

Сообщение от ksa (Сообщение 265261)
Твой tt есть объект...

tt[0] = 11;

Изменеие/создание свойства объекта...

Но поскольку ты занаследовался от массива (это так же объект) - у тебя есть метод push()

tt.push(99);

Выполнилось создание элемента массива, изменилась длина

alert(tt.[0]); // пишет 99

Потому как имя свойства объекта "совпало" с первым элементом массива...

Что-то такое.

Понял, спасибо.

Тогда такой вопрос: я хочу сделать "класс" полностью повторяющий функционал массива (т.е. можно было бы устанавливать значения в массиве конструкцией вида: array[n] = val; ) + набор своих методов, но при этом не затронув нативный Array() и его прототип. Как такое реализовать?

Цитата:

Сообщение от рони (Сообщение 265270)
интересно как это может работать?

Торопился, и точку лишней написал (

danik.js 31.07.2013 19:20

Цитата:

Сообщение от weeklyTea
Как такое реализовать?

Так и реализуй. А в чем сложность возникла?

devote 31.07.2013 19:30

Цитата:

Сообщение от danik.js
Так и реализуй. А в чем сложность возникла?

сложность тут в том что это работать не будет
function MyArray() {
}
MyArray.prototype = Array.prototype;
var a = new MyArray();
a[0] = 'test'; // не работает
alert([a, a.length]);
a.push('haha'); // работает
alert([a, a.length]);
Для реализации объектов типа List (массивов) нужны как минимум магические акцессоры(getters/setters) каковых в JavaScript не существует.

danik.js 31.07.2013 19:34

Невнимательно прочитал. Да, действительно. Можно только в браузерах, поддерживающих __proto__. Можно же создать массив и подменить его прототип на свой (кстати этот прием используется в zepto.js).

devote 31.07.2013 19:40

Цитата:

Сообщение от danik.js
Можно только в браузерах, поддерживающих __proto__

вот именно, а это значит что ИЕ7-8-9-10 в пролете, но вот ИЕ11 уже поддерживает свойство __proto__, хоть оно и не стандартное, но мелкософт решил его добавить в ИЕ11

danik.js 31.07.2013 19:44

Можно еще создать фрейм и взять оттуда конструктор Array и делать с прототипом че угодно. Но это очень грязный трюк и вобще я так не пробовал даже )

devote 31.07.2013 19:56

Цитата:

Сообщение от danik.js
Но это очень грязный трюк и вобще я так не пробовал даже

ну это да, извращение конечно)))
var MyArray = document.documentElement.firstChild.appendChild(document.createElement('iframe')).contentWindow.Array;

// расширяем Array
MyArray.prototype.testFunc = function() {}

alert(new MyArray().testFunc);
alert(new Array().testFunc);

var a = new MyArray();
a[0] = 'test';
alert([a, a.length]);


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