Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/462.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以用JavaScript创建自己的数组对象吗?_Javascript_Arrays_Object - Fatal编程技术网

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

我可以用JavaScript创建自己的数组对象吗?,javascript,arrays,object,Javascript,Arrays,Object,我创建了一个JavaScript应用程序,它有很多数组操作(排序、过滤等) 目前我的功能如下: function (myArray, arg1, arg2,...) 其中myArray是我正在处理的数组,arg1、arg2,。。。函数用于修改数组的参数 function MyArray() {} MyArray.prototype = []; MyArray.prototype.constructor = MyArray; var instance = new MyArray; instanc

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

目前我的功能如下:

function (myArray, arg1, arg2,...)
其中myArray是我正在处理的数组,arg1、arg2,。。。函数用于修改数组的参数

function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.constructor = MyArray;
var instance = new MyArray;
instance[0] = 0;
alert(instance.length);  // alerts 0
我认为在对象和参数之间有一个清晰的分离会更整洁(一个jQuery):

我知道我可以使用Array.prototype将我的函数添加到所有数组中,但这似乎太重了,因为我添加的函数实际上是针对我的情况的,并且通常在数组中没有意义。我也知道我可以创建一个对象,但是我不会从JavaScript中可用的数组方法(indexOf、filter等)中获益


是否有一种方法可以创建自己的数组对象,该方法可以继承默认数组方法并允许我添加自己的数组方法

No.
Array
不能被子类化,并且仍然像数组一样工作。具体而言,
length
属性不会更改以反映从数组中添加或删除的元素

function MyArray() {}
MyArray.prototype = [];
MyArray.prototype.constructor = MyArray;
var instance = new MyArray;
instance[0] = 0;
alert(instance.length);  // alerts 0
发生这种情况的原因是,只有通过
newarray
或类似
[]
的语法糖创建的对象才对长度进行特殊处理


上面的
new MyArray
创建了一个常规对象,其原型是
数组
,但是
new
操作符没有检查对象的原型是否是
数组
,并设置特殊的
长度
处理。

是,只需使用

扩展
阵列原型
,您只需将函数直接添加到对象而不是原型:

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

您有两个选择:

选项一是通过向
数组添加新方法来扩展
对象:

Array.prototype.myMethod = function(arg1, arg2)
{
    // Use 'this' to access the array.
}
优点是每个javascript数组现在都有这个额外的方法。当多个(外部)javascript库尝试添加相同的方法时,这也可能是一个缺点。此外,这个新方法将出现在
for(myArray中的var项)
构造中,这可能会有问题

选项二是为扩展阵列创建“工厂方法”:

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

    return array;
};
现在,您可以编写以下内容来创建新的扩展阵列:

var arr = MyExtendedArray();

我创建了这个数组,这是我的数组版本,但是在这个数组中做了一些修改,你不能像原始数组那样更改长度

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];
    }
}
}
通过在末尾添加姓氏“Nawaz”来修改每个名字,如“Ali”变成“Ali Nawaz”


继续使用这个函数,你不需要oopRight中的所有东西,但我喜欢它的干净程度,例如链接或定义默认选项/参数。我认为工厂方法正是我特定应用程序所需要的。这太明显了…我看不出来:-)谢谢!奇怪的是,如果使用.push()方法将数据存储到数组中,则长度会正确更新。@ZlatinZlatev,最近的EcmaScript候选脚本的目标是允许对数组、RegExp和Date等对象进行子类化,因此这个答案可能不会正确太久。也许你在最近的JavaScript引擎中看到了一些行为,这些引擎实现了对数组子类化的支持。好吧,至少最新版本的Chrome和最新版本的Rhino引擎(直到今天——2015年8月31日)确实有你我描述的行为。
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"}