Могу ли я создать свой собственный объект массива в JavaScript? - PullRequest
5 голосов
/ 10 февраля 2012

Я создал приложение JavaScript, которое имеет множество манипуляций с массивами (сортировка, фильтрация и т. Д.).

В настоящее время мои функции таковы:

function (myArray, arg1, arg2,...)

где myArray - массив, над которым я работаю, а arg1, arg2, ... - аргументы, используемые функцией для изменения массива.

Я думаю, что было бы лучше иметь четкое разделение между объектом и аргументами (а-ля jQuery):

myArray.function(arg1, arg2,...)

Я знаю, что мог бы использовать Array.prototype, чтобы добавить свою функцию ко всем массивам, но это кажется слишком тяжелым, поскольку добавляемые мной функции действительно специфичны для моего случая и не имеют смысла для массивов в целом. Я также знаю, что мог бы создать объект, но тогда я не получил бы преимущества от методов массива, доступных в JavaScript (indexOf, filter и т. Д.).

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

Ответы [ 5 ]

8 голосов
/ 10 февраля 2012

У вас есть два варианта:

Первый вариант - расширить объект Array, добавив в него новые методы:

Array.prototype.myMethod = function(arg1, arg2)
{
    // Use 'this' to access the array.
}

Преимущество состоит в том, что каждый массив javascript теперь будет иметь этот дополнительный метод. Это также может быть недостатком, когда несколько (внешние) библиотеки JavaScript пытаются добавить одни и те же методы. Кроме того, этот новый метод появится в for(var item in myArray) конструкциях, которые могут быть проблематичными.

Второй вариант - создать «фабричный метод» для расширенного массива:

function MyExtendedArray = function()
{
    var array = [];
    array.myMethod = function(arg1, arg2) {
        // Use 'this' or 'array' to access the array.
    };

    return array;
};

Теперь вы можете написать это для создания нового расширенного массива:

var arr = MyExtendedArray();
5 голосов
/ 10 февраля 2012

Вы можете просто добавить функцию непосредственно к вашему объекту, а не к прототипу:

var myArray = new Array();
myArray.myFunc = function(){ /* do stuff! */ };
myArray.myFunc();
4 голосов
/ 10 февраля 2012

Нет.Array не может быть разделено на подклассы и все еще вести себя как массив.В частности, свойство length не изменится, чтобы отразить элементы, которые добавлены или удалены из массива.

function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.constructor = MyArray;
var instance = new MyArray;
instance[0] = 0;
alert(instance.length);  // alerts 0

Причина этого заключается в том, что только объекты, созданные с помощью new Array или синтаксические сахароподобные[] имеют специальную обработку по длине.

Приведенное выше new MyArray создает обычный объект, прототип которого является Array, но нет ничего в операторе new, который проверяет, является ли прототипОбъект является Array и устанавливает специальную обработку length.

0 голосов
/ 19 марта 2019

Я создаю эту версию, которая является моей версией массива, но с некоторыми изменениями в этом массиве вы не можете изменить длину, как с исходным массивом

let ary = [1,2,3];
console.log(ary.length); //3

ary.length = 999;
console.log(ary.length); //999

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

let myArray = new MyArray(1,10); //new MyArray(from,to)
console.log(myArray.length); // 10

myArray.length = 999;
console.log(myArray.length); // 10  //still 10 because .length is a get function 

код моего массива

let _getlength = {}, _inclength = {}, _declength = {};

class MyArray{

 constructor(from, to)
  {
    this.key = Symbol('ignore this key');

    //i make it a closer because i don't want any one to change the length
    // by this my length become private and can be only incremented by one by "_inclength()" function or
    [_getlength[this.key], _inclength[this.key], _declength[this.key]] = (
        () =>
        {
            let length = 0;

            let getLength = () =>
            {
                return length;
            };

            let inclength = () =>
            {
                length++;

                this[length - 1] = 0;

                return length;
            };

            let declength = () =>
            {
                return --length;
            };


            return [getLength, inclength, declength];
        }
    )();

    if (from != null || to != null)
    {
        for (let num = from; num <= to; num++)
        {
            this.push(num);
        }
    }

}

push(value)
{
    this[this.IncreaseLengthByOne() - 1] = value;
}

unshift(value)
{
    this.addAt(0, value)
}

addAt(index, value)
{
    this.IncreaseLengthByOne();
    for (let i = this.length - 2; i >= index; i--)
    {
        this[i + 1] = this[i];
    }

    this[index] = value;
}

removeAt(index)
{

    for (let i = index; i < this.length - 1; i++)
    {
        this[i] = this[i + 1];
    }

    this.pop();
}

pop()
{
    _declength[this.key]();
    delete this[this.length];
}

get length()
{
    return _getlength[this.key]();
}

IncreaseLengthByOne()
{
    return _inclength[this.key]();
}

forEach(callback)
{
    for (let i = 0; i < this.length; i++)
    {
        callback(this[i], i, this);
    }
}

map(callback)
{
    let myArray = new MyArray();
    for (let i = 0; i < this.length; i++)
    {
        myArray.push(callback(this[i], i, this));
    }

    return myArray;
}


// if you don't know what it is then go and learn what generators are! what Symbol(primitive type) is and what Symbol.iterator is then
// come back
* [Symbol.iterator]()
{
    for (let i = 0; i < this.length; i++)
    {
        yield this[i];
    }
}
}

примеры: создайте массив имен и добавьте к нему «Али», «Хади», «Янтарь»

let names = new MyArray();

names.push('Ali');
names.push('Hadi');
names.push('Amber');
console.log(names); // MyArray {0: "Ali", 1: "Hadi", 2: "Amber"}

изменить каждое имя, добавив в конце фамилию "Наваз" Как "Али" станет "Али Наваз"

let fullNames = names.map(nam => nam +' Nawaz');
console.log(fullNames); //MyArray {0: "Ali Nawaz", 1: "Hadi Nawaz", 2: "Amber Nawaz"}
0 голосов
/ 10 февраля 2012

Да, просто расширьте Array prototype с помощью jQuery.extend

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...