我可以在JavaScript中创建自己的数组对象吗?

时间:2012-02-10 19:24:29

标签: javascript arrays object

我创建了一个JavaScript应用程序,它有很多数组操作(排序,过滤等)。

目前我的功能是这样的:

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

其中myArray是我正在处理的数组,而arg1,arg2,...是函数用来修改数组的参数。

我认为在对象和参数之间进行明确的分离会更简洁(la jQuery):

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

我知道我可以使用Array.prototype将我的函数添加到所有数组中,但是这看起来太重了,因为我添加的函数对我的情况来说非常具体,而且对数组一般没有意义。我也知道我可以创建一个对象,但是我不会受益于JavaScript中可用的数组方法(indexOf,filter等)。

有没有办法可以创建自己的数组对象,继承默认的数组方法并允许我添加自己的数组对象?

5 个答案:

答案 0 :(得分:8)

你有两个选择:

选项一是通过向其添加新方法来扩展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();

答案 1 :(得分:5)

您只需将函数直接添加到对象而不是原型:

var myArray = new Array();
myArray.myFunc = function(){ /* do stuff! */ };
myArray.myFunc();

答案 2 :(得分:4)

没有。 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处理。

答案 3 :(得分:0)

是的,只需使用jQuery.extend

扩展Array prototype即可

答案 4 :(得分:0)

我创建了这个数组,这是我的数组版本,但是对此数组进行了一些修改,您无法像使用原始数组一样更改长度

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];
    }
}
}

示例: 创建一个名称数组,并在其中添加“ Ali”,“ Hadi”,“ Amber”

let names = new MyArray();

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

通过在末尾添加姓氏“ Nawaz”来修改每个名称像“ Ali”成为“ Ali Nawaz”

let fullNames = names.map(nam => nam +' Nawaz');
console.log(fullNames); //MyArray {0: "Ali Nawaz", 1: "Hadi Nawaz", 2: "Amber Nawaz"}