Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как создать массив с особым прототипом? (https://javascript.ru/forum/misc/36783-kak-sozdat-massiv-s-osobym-prototipom.html)

danik.js 27.03.2013 12:42

Как создать массив с особым прототипом?
 
Нужно создать массив со своим кастомным прототипом.

Если в браузере доступно свойство __proto__, то можно сделать так:

function MyArray () {
    var instance = []
    instance.__proto__ = arguments.callee.prototype
    return instance
}
MyArray.prototype.myFunction = function () {}

var myArray = new MyArray()
alert( typeof myArray.myFunction )


А как сделать такое же без __proto__ ?

Aetae 27.03.2013 13:27

Мб так:
function MyArray () {}
MyArray.prototype = Array.prototype;
MyArray.prototype.myFunction = function () {
	return this[0] + this[1]
}
 
var myArray = new MyArray()
alert([ 
	typeof myArray.myFunction,
	myArray instanceof Array,
	typeof myArray
])

myArray.push(5)
myArray.push(3)
alert([
	myArray.length,
	myArray.myFunction()
])

...но зачем?

danik.js 27.03.2013 13:51

Aetae
function MyArray () {}
MyArray.prototype = Array.prototype;
MyArray.prototype.myFunction = function () {
    return this[0] + this[1]
}
  
var myArray = new MyArray()

// во-первых мы изменили прототип Array, но это решаемо
alert( typeof [].myFunction )

// во-вторых, мы получили таки объект, а не массив
alert( Array.isArray(myArray) )
alert( Object.prototype.toString.call(myArray) )


А должно быть так:
function MyArray () {
    var instance = []
    instance.__proto__ = arguments.callee.prototype
    return instance
}
MyArray.prototype.myFunction = function () {}
 
var myArray = new MyArray()

alert( typeof [].myFunction )
alert( Array.isArray(myArray) )
alert( Object.prototype.toString.call(myArray) )


Зачем это? Пытаюсь заставить библиотеку Zepto работать с IE. А там как раз использется массив, а не объект.
Да и вообще интересно - возможно ли так сделать без __proto__

rgl 27.03.2013 14:11

var MyArray = function() {
  var _myPrototype = {
    joinReverse : function(s) { return this.slice(0).reverse().join(s); }
  }
  return function() {
    var ret = Array.apply( null, arguments );
    for( var i in _myPrototype )
      // if( typeof _myPrototype[i] == "function" )
        ret[i] = _myPrototype[i];
    return ret;
  }
}();

var test = MyArray( 1, "bb", 333 );

alert( test.joinReverse( " - " ) );

Aetae 27.03.2013 14:15

Цитата:

Сообщение от danik.js (Сообщение 242926)
// во-первых мы изменили прототип Array, но это решаемо

Эт да, бывает)
Цитата:

Сообщение от danik.js (Сообщение 242926)
Зачем это? Пытаюсь заставить библиотеку Zepto работать с IE. А там как раз использется массив, а не объект.

Лол, Zepto прямо позиционируется как jquery без ie.) Хочешь поддержку ie - откатись на jquery. (Там так и написано на главной: "If you need to support Internet Explorer, you can fall back on jQuery.")
Цитата:

Сообщение от danik.js (Сообщение 242926)
Да и вообще интересно - возможно ли так сделать без __proto__

Можно сделать без __proto__ - используюя новомодные методы Object(которые в ie конечно не работают). =)
Ну или вручную навешивать на каждый создаваемый массив методы, что, естесно, скажется на производительности и будет вылезать в for in.

...upd: пока писал - последний вариант реализовал rgl.)

megaupload 27.03.2013 16:21

function MEGAArray (){};
MEGAArray.prototype = new Array;

MEGAArray.prototype.godOfJavascript = function(){};


Прототипное наследование не, не слышали?

rgl 27.03.2013 17:40

Цитата:

Сообщение от megaupload (Сообщение 242947)
function MEGAArray (){};
MEGAArray.prototype = new Array;

MEGAArray.prototype.godOfJavascript = function(){};


Прототипное наследование не, не слышали?

Разумеется, это первое, что приходит в голову каждому, знающему JavaScript на более-менее нормальном уровне. Но каждый (м-м-м, почти каждый) прежде чем писать в форуме, проверил, и убедился что это не работает. Дело в том, что у полученного объекта отсутствует свойство length (точнее оно присутствует, но не свое, а наследуемое, а там оно ноль). Из-за этого методы массива не работают. Свойство length можно добавить, но оно не будет автоматически модифицироваться как должно у массива.
function MEGAArray (){};
MEGAArray.prototype = new Array;

var test = new MEGAArray();
test[0] = "a";
test[1] = "bb";
test[2] = "ccc";

alert( test.length );

rgl 27.03.2013 17:48

Цитата:

Сообщение от Aetae (Сообщение 242931)
Ну или вручную навешивать на каждый создаваемый массив методы, что, естесно, скажется на производительности и будет вылезать в for in.

Как это скажется на производительности, не знаю, но думаю что сильно не ухудшит, т.к. добавленные методы будут находиться ближе, прямо тут а не по цепочке. Другое дело, наверно памяти больше займет. А вылезать в for in будет в любом случае, и если в прототип добавить тоже.

danik.js 27.03.2013 18:45

rgl, твой вариант некудышный, ибо методов много, а конструктор вызывается часто. Так что думаю потребление ресурсов возрастет ощутимо. Кроме того, прототипа то и нет получается ). А нужно чтобы был прототип. И добавляя метод в прототип мы автоматом получаем его у уже созданных экземпляров.

megaupload, этот вариант я пробовал. В консоли объект действительно выглядит как [массив], вот только Array.isArray не обманешь. Ну и toString также выдает [object Object]

А то, что length не обновляется - это не беда. Работа с коллекцией всеравно идет через методы, а не напрямую.

Цитата:

Сообщение от Aetae
Лол, Zepto прямо позиционируется как jquery без ie.) Хочешь поддержку ie - откатись на jquery. (Там так и написано на главной: "If you need to support Internet Explorer, you can fall back on jQuery.")

Дело в том, что это по большей части касается IE6-8.
В девятке и уж тем более в десятке есть все, что нужно. Так что отсутствие поддержки IE9-10 - это всего лишь наследие zepto. А корень проблемы в использовании __proto__ . Кстати, кто-то говорил что это свойство добавили в стандарт, это так?

Если заглянуть сюда https://github.com/madrobby/zepto/issues/ то видно, что не я один хочу поддержки IE.
Цитата:

Сообщение от Aetae
используюя новомодные методы Object

Че за методы такие?

megaupload 27.03.2013 19:21

function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.toString  = function(){alert('ну вы нубы')};

var q = new MyArray();

q.push(1);
q.push(1);

alert(q.length);

q+"";


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