Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Унаследовать Array (https://javascript.ru/forum/misc/25136-unasledovat-array.html)

inst 26.01.2012 17:37

Унаследовать Array
 
Добрый день.

Почитал о наследовании в JavaScript. Вкратце, захотел сделать List, который мог бы фильтровать добавляемые в него данные, при этом весь функционал чтобы повторял обычный Array. Вот к чему пришёл:
util.List = function () {
	Array.apply(this, arguments);
};
util.List.prototype = new Array();
util.List.prototype.move = function (from, to) {
	if (typeof from === 'string') {
		from = Number(from);
	}
	if (typeof to === 'string') {
		to = Number(to);
	}
	if (typeof to !== 'number' ||
	   (typeof to === 'number' && isNaN(to))
	   ) {
		return false;
	}
	if (typeof from !== 'number' ||
	   (typeof from === 'number' && isNaN(from))
	   ) {
		return false;
	}

	if (typeof this['onMove'] === 'function') {
		if (this.onMove(from, to) === false) {
			return false;
		}
	}

	var tmp = this.splice(from, 1);
	this.splice(to, 0, tmp);
	return this;
};
proxyFn = function (obj, fn, args) {
	var fnUCase = fn.charAt(0).toUpperCase() + fn.slice(1),
		result;
	if (typeof obj['on' + fnUCase] === 'function') {
		if (obj['on' + fnUCase].apply(obj, args) === false) {
			return false;
		}
	}
	result = Array[fn].apply(obj, args);
	if (typeof result === 'undefined') {
		return true;
	} else {
		return result;
	}
};
util.List.prototype.push = function () { return proxyFn(this, 'push', arguments); };
util.List.prototype.shift = function () { return proxyFn(this, 'shift', arguments); };
util.List.prototype.join = function () { return proxyFn(this, 'join', arguments); };
util.List.prototype.concat = function () { return proxyFn(this, 'concat', arguments); };
util.List.prototype.splice = function () { return proxyFn(this, 'splice', arguments); };
util.List.prototype.pop = function () { return proxyFn(this, 'pop', arguments); };
util.List.prototype.unshift = function () { return proxyFn(this, 'unshift', arguments); };
util.List.prototype.slice = function () { return proxyFn(this, 'slice', arguments); };
util.List.prototype.reverse = function () { return proxyFn(this, 'reverse', arguments); };
util.List.prototype.sort = function () { return proxyFn(this, 'sort', arguments); }
Думал, после этого будет достаточно:
var lst = new util.List();
lst.push(1);
lst.push(2);
lst.push(3);
Но
console.log(lst);
не показывает никаких данных внутри объекта, кроме определённых выше функций.

Вопрос: В JavaScript нельзя унаследовать массив?

UPDATE: Ошибка была в строчке 41. Должно быть так:
result = Array.prototype[fn].apply(obj, args);

Livaanderiamarum 26.01.2012 17:45

можно

Gozar 26.01.2012 17:48

Цитата:

Сообщение от inst (Сообщение 153055)
В JavaScript нельзя унаследовать массив?

Что значит унаследовать массив? Массив это набор данных, его не наследуют.

Что такое:
new lt.util.List();

Livaanderiamarum 26.01.2012 17:48

Что такое List?

inst 26.01.2012 18:02

Цитата:

Сообщение от Gozar (Сообщение 153060)
Что такое:
new lt.util.List();

Извините, опечатка, в посте исправил. Но проблема не в ней.

Цитата:

Сообщение от Gozar (Сообщение 153060)
Что значит унаследовать массив? Массив это набор данных, его не наследуют.

В JavaScript же всё - объекты. И Array - не исключение. Я не сам массив хочу унаследовать, а его функционал.

inst 26.01.2012 18:03

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153061)
Что такое List?

Всё в посте.

inst 26.01.2012 18:03

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153059)
можно

А почему тогда данные не добавляются по push?

Livaanderiamarum 26.01.2012 18:04

Цитата:

Сообщение от inst (Сообщение 153071)
Всё в посте.

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

Nekromancer 26.01.2012 18:10

var A = function(){};
A.prototype = [];
var a = new A;
a.push('vasea', 'test');
alert(a);
alert((Array.isArray || function(o){Object.prototype.toString.call(o) == '[object Array]'})(a));


В общем такое можно, но только в новых браузерах. IE<9 не проканает, хотя есть и свои хаки.

inst 26.01.2012 18:15

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153073)
Прочитав пост задаю вопрос, что такое лист и что он должен делать?

Ну, я же указал в начале поста:
Цитата:

List, который мог бы фильтровать добавляемые в него данные
Т.е. это такой объект, создав экземпляр которого, я бы мог получить доступ ко всем функциям массива (например, push), определить функцию onPush(), которая бы вызывалась перед непосредственно добавлением данных и служила в качестве фильтра, пропуская или нет добавляемые данные.

Как пример:
var list = new List();
list.onPush = function(data) {
if (typeof data !== 'number') {
return false;
}
return true;
}
Затем:
list.push('строка'); // и эта строка не добавится
list.push(777); // а с число - добавится
list.push(function() {}); // и ничего кроме цифр туда не добавишь

В результате в list должен добавиться только один элемент:
list[0] == 777;
Как-то так.

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153073)
но за грубый ответ помогать не буду и вопрос снимаю

Я и не думал грубить.

inst 26.01.2012 18:18

Цитата:

Сообщение от Nekromancer (Сообщение 153075)
var A = function(){};
A.prototype = [];
var a = new A;
a.push('vasea', 'test');
alert(a);
alert((Array.isArray || function(o){Object.prototype.toString.call(o) == '[object Array]'})(a));


В общем такое можно, но только в новых браузерах. IE<9 не проканает, хотя есть и свои хаки.

Спасибо. Значит, ответ отрицательный.

Livaanderiamarum 26.01.2012 18:19

inst,
а, да, щас сделаю))) я просто не понял что за лист я думал ты список какой то сделать хочешь.

Livaanderiamarum 26.01.2012 18:20

Цитата:

Сообщение от inst (Сообщение 153080)
Спасибо. Значит, ответ отрицательный.

Нет нет щас сделаю)

melky 26.01.2012 18:24

один вопрос - List должен фильтровать поступающие данные, если они назначаются так ?
myList[ 5 ] = "тут что-то";

inst 26.01.2012 18:26

Цитата:

Сообщение от melky (Сообщение 153086)
один вопрос - List должен фильтровать поступающие данные, если они назначаются так ?
myList[ 5 ] = "тут что-то";

Ну, это конечно было бы здорово. Только разве это возможно? o.0

Livaanderiamarum 26.01.2012 18:31

Что хочу сказать, сделать такой List есть миллиард способов, ты хочешь сделать именно выбранным тобой способом?

То есть сделать обьект который бы использовал внутри себя массив и являлся для него как бы оболочкой. При том включал бы в себя все его методы, при том на все эти меоды можно было бы повесить фильтр типа
onНазваниеМетода и если этот фильтр возвратит true, то метод срабатывал бы, если возвратит false , то не срабатывал бы)? так?

inst 26.01.2012 18:35

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153091)
Что хочу сказать, сделать такой List есть миллиард способов, ты хочешь сделать именно выбранным тобой способом?

То есть сделать обьект который бы использовал внутри себя массив и являлся для него как бы оболочкой. При том включал бы в себя все его методы, при том на все эти меоды можно было бы повесить фильтр типа
onНазваниеМетода и если этот фильтр возвратит true, то метод срабатывал бы, если возвратит false , то не срабатывал бы)? так?

Да, List, который как и любой Array можно было бы перебирать в конструкциях типа for(var item in list) {
if (list.hasOwnProperty(item)) {console.log(list[item])}
}
и при этом дополнительно имелся бы описанный тобой функционал фильтра.

inst 26.01.2012 18:37

На самом деле, мне просто непонятно, что не так с моим кодом?
Но за помощь, конечно, всем большое спасибо :)

Livaanderiamarum 26.01.2012 18:55

Цитата:

Сообщение от inst (Сообщение 153094)
На самом деле, мне просто непонятно, что не так с моим кодом?
Но за помощь, конечно, всем большое спасибо :)

ты понимаешь что тебе придется переписывать все методы которые будут использовать фильтры)? я перепишу только один, остальное ты

Livaanderiamarum 26.01.2012 18:59

Собираешься ли ты менять фильтры на ходу несколько раз, собираешься ли ты менять фильтры у отдельных листов? есть ли фильтры по умолчанию?

_
вот если бы мне нужен был массив который бы принимал только числа, я бы сделал не так тупо как ты я бы сделал так:

inst 26.01.2012 19:04

Цитата:

Сообщение от Livaanderiamarum (Сообщение 153107)
Собираешься ли ты менять фильтры на ходу несколько раз, собираешься ли ты менять фильтры у отдельных листов? есть ли фильтры по умолчанию?

_
вот если бы мне нужен был массив который бы принимал только числа, я бы сделал не так тупо как ты я бы сделал так:

Я собираюсь сделать этот List частью API, а от него унаследовать несколько других объектов, которые по сути нужны просто для отслеживания изменений. Менять фильтры не буду, просто определю нужные в прототипах унаследованных объектов. По умолчанию ничего не надо, вроде бы.

А как?

Livaanderiamarum 26.01.2012 19:12

(function(name) {
	var prototype = {}
	prototype.__proto__ = Array.prototype;
	with (prototype) {
		// ниже перекрываешь методы добавляешь фильтры и.т.п.












        // раз перекрыли -------------------------------------------------------
		push = function(arg) {
			if(typeof agr == 'string'){
				//эта строчка использует метод массива
				Array.prototype.push.apply(this, arguments)
			}
		};








        // два перекрыли -------------------------------------------------------
		blablabla = function(arg) {
		    alert(arg)
		};














	
	}
	window[name] = function() {
		var list = []
		list.__proto__ = prototype
		return list
	}
})('List')



новые листы создаются без new чтобы удобнее было, просто
var list = List()

inst 26.01.2012 19:33

В общем, суть та же, только для более узкого круга задач :)

Я разобрался, ошибка была в том, что я в proxyFn вместо
result = Array.prototype[fn].apply(obj, args);
вызывал метод не из прототипа.

Спасибо за помощь :)

Livaanderiamarum 26.01.2012 19:54

Цитата:

Сообщение от inst
Спасибо за помощь

Не вопрос бро))

poorking 26.01.2012 20:15

inst,
Обратите внимание на splice, я не помню как именно, но метод работал не корректно, а может и не только он, то ли элементы не удалялись, то ли индексы не менялись, тоже как-то давно очень захотелось подобную штуку сделать, потом понял ,что затея вобщем-то, просто ради затеи...

DreamTheater 26.01.2012 20:47

function List() {
    alert('Hello, I am List constructor!');
};

List.prototype = Object.create(Array.prototype, {
    move: {
        value: function () {
             alert('I am custom method "move"!');
        }
    }
});

new List().move();

Gozar 26.01.2012 21:46

>= IE9 и Опера 11.60, но если для себя то уже можно ж;)


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