"расширить бы массив", или "расскажите как работают прототипы"
Есть следующий код:
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
можете объяснить такое поведение? ) |
Цитата:
tt[0] = 11; Изменеие/создание свойства объекта... Но поскольку ты занаследовался от массива (это так же объект) - у тебя есть метод push() tt.push(99); Выполнилось создание элемента массива, изменилась длина alert(tt.[0]); // пишет 99 Потому как имя свойства объекта "совпало" с первым элементом массива... Что-то такое. |
Цитата:
|
Цитата:
Тогда такой вопрос: я хочу сделать "класс" полностью повторяющий функционал массива (т.е. можно было бы устанавливать значения в массиве конструкцией вида: array[n] = val; ) + набор своих методов, но при этом не затронув нативный Array() и его прототип. Как такое реализовать? Цитата:
|
Цитата:
|
Цитата:
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 не существует. |
Невнимательно прочитал. Да, действительно. Можно только в браузерах, поддерживающих __proto__. Можно же создать массив и подменить его прототип на свой (кстати этот прием используется в zepto.js).
|
Цитата:
|
Можно еще создать фрейм и взять оттуда конструктор Array и делать с прототипом че угодно. Но это очень грязный трюк и вобще я так не пробовал даже )
|
Цитата:
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]);
|
Из постов выше сделал вывод, что то, что я хочу сделать, сделать нельзя, т.к. в js нет возможности переопределить (наследуя) сеттер []. Верно? (
|
Вроде через ES6 Proxy можно.
|
Цитата:
А в любой документации при наследовании используется только слово "объект"... |
Короче сидел мудрил и вот че намудрил (работает только в Firefox)
var MyArray = function(){
var internal = Object.create(null, {length: {value: 0, enumerable: false, writable: true}});
var proto = MyArray.prototype;
return Proxy.create({
get: function(receiver, name) {
if (name in internal) {
return typeof internal[name] == 'function' ? internal[name].bind(internal) : internal[name];
}
if (name in proto) {
return typeof proto[name] == 'function' ? proto[name].bind(internal) : proto[name];
}
return undefined;
},
set: function(receiver, name, value) {
if (name === 'length') {
throw 'Not implemented';
}
if (!isNaN(name) && (name == +name)) {
name = +name;
if (internal.length <= name) {
internal.length = name + 1;
}
}
internal[name] = value;
}
});
};
MyArray.prototype.push = function() {
for (var i = 0; i < arguments.length; i++) {
this[this.length++] = arguments[i];
}
};
MyArray.prototype.join = function(separator) {
var values = [];
for (var i = 0; i < this.length; i++) {
values.push(this[i]);
}
return values.join(separator);
}
var a = new MyArray();
a.push('x','y')
console.log(a.join())
console.log(a.length)
|
| Часовой пояс GMT +3, время: 18:12. |