"расширить бы массив", или "расскажите как работают прототипы"
Есть следующий код:
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, время: 13:36. |