Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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。创建类似数组的对象。是否可以使.length自动递增?_Javascript_Arrays_Object - Fatal编程技术网

Javascript。创建类似数组的对象。是否可以使.length自动递增?

Javascript。创建类似数组的对象。是否可以使.length自动递增?,javascript,arrays,object,Javascript,Arrays,Object,关于创建和继承类似数组的对象有很多,但我的一个问题仍然没有回答:是否可以以某种方式向对象添加自动递增的.length属性? 示例脚本: function ArrayLike(){ this.length=0; this.splice=[].splice; } var Arr=new ArrayLike(); Arr[0]=0; Arr[1]=1; alert(Arr.length); //alerts "0" instead of "2" 当然,我可以添加一些方法,如: fun

关于创建和继承类似数组的对象有很多,但我的一个问题仍然没有回答:是否可以以某种方式向对象添加自动递增的
.length
属性?
示例脚本:

function ArrayLike(){
    this.length=0;
    this.splice=[].splice;
}
var Arr=new ArrayLike();
Arr[0]=0;
Arr[1]=1;
alert(Arr.length); //alerts "0" instead of "2"
当然,我可以添加一些方法,如:

function ArrayLike(){
    this.length=0;
    this.splice=[].splice;
    this.push=function(toadd){
        this[this.length++]=toadd;
    }
}
但这不是我想要做的

那么,当我以
Arr[N]='blah-blah-blah-blah'
的方式向对象添加某些内容时,是否可以增加.length

是否可以以某种方式添加autoincrement.length属性

不是真的;至少,您不能做
Array
围绕
length
和索引属性所做的所有事情

在支持ES5的环境中,可以使用getter和setter函数将
length
设置为属性。但是很难确定
长度应该是多少,因为(到目前为止)还没有“全面”的设置方法,当代码如下所示:

arr[1] = "foo";
…运行。(ES6很可能通过代理捕获所有属性设置器。)

因此,您的
长度
必须从对象内容中计算出来,这不是很有效,例如:

var explicitLength;
Object.defineProperty(this, "length", {
    get: function() {
        var length;

        // Find our length from our max index property
        length = Object.keys(this).reduce(function(maxIndex, key) {
            var index = key === "" ? NaN : +key;
            if (!isNaN(index) && index > maxIndex) {
                return index;
            }
            return maxIndex;
        }, -1) + 1;

        // If we have an explicitly-set length, and it's greater,
        // use that instead. Note that if explicitLength is
        // `undefined`, the condition will always be false.
        if (explicitLength > length) {
            length = explicitLength;
        }

        return length;
    },
    set: function(value) {
        explicitLength = value;
        // You might choose to have code here removing properties
        // defining indexes >= value, likes Array does
    }
});
请注意,即使我们有一个明确设置的长度,我们仍然必须检查自然长度是否更大,以处理:

arr.length = 2;
arr[5] = "foo";
console.log(arr.length); // Should be 6, not 2
在属性检索上做那么多工作显然不是一件好事,所以我会避开这类事情


上面我说“…所以我会避开这类事情。”

那很好,但是你应该怎么做呢

假设您有您想要的功能
nifty
spiffy
。您有两个现实的选择:

  • 使用实际的数组,并将自定义方法混合到每个数组实例中

  • 增强阵列。原型

  • #1使用实际数组并在方法中混合 您可以在一个方便的对象上定义方法,例如
    ArrayMixin

    var ArrayMixin = {
        nifty: function() {
            // ...do something nifty with `this`
        },
        spiffy: function() {
            // ...do something spiffy with `this`
        }
    };
    
    然后使用生成器函数创建阵列:

    function createArray(arr) {
        arr = arr || []; // `arr` is optional
        extend(arr, ArrayMixin);
        return arr;
    }
    
    你会问,这个扩展功能是什么?将属性从一个对象复制到另一个对象的东西。如果您使用任何库或框架(jQuery、下划线、Angular、PrototypeJS等等),它们很可能具有某种类型的
    extend
    函数来实现这一点。通常看起来像这样(这是非常即兴的)

    …而且
    a
    上有
    nifty
    spiffy

    例如:

    var ArrayMixin={
    漂亮的:函数(){
    this.forEach(函数(条目、索引){
    此[索引]=entry.toUpperCase();
    },这个);
    归还这个;
    },
    spiffy:function(){
    this.forEach(函数(条目、索引){
    此[索引]=entry.toLowerCase();
    },这个);
    归还这个;
    }
    };
    函数createArray(arr){
    arr=arr | |[];/`arr`是可选的
    扩展(arr、ArrayMixin);
    返回arr;
    }
    功能扩展(目标){
    变量arg,对象j,键;
    for(arg=1;arg
    
    
    
    为什么要这样做?只要使用
    数组()
    ,并向其添加额外的属性(如果使用)。在JavaScript中,
    Array
    s也是对象。它们可以有属性:
    var Arr=[0,1];arr.myProperty=“foobar”不过,我并不是说这些都是好主意。你最好的选择可能是将长度作为一种方法,而不是属性。请不要否决这个问题。它写得不错,在任何其他指标上都不会失败。如果他不明白为什么这不是一个好主意,那么答案应该解释为什么,仅此而已。@MadBrozzeR:复制
    数组
    功能的一部分确实不会获得任何性能。它是一个本机对象,在现代浏览器中得到了很好的优化。编写您自己的实现将否定这种优化,更不用说您必须跳转才能真正使其工作。@MadBrozzeR:“在迭代时赢得一点性能…”我看不到使用您自己的对象比本机数组有任何好处,您能解释一下您认为从何处获得这种好处吗?“…或者只是不让它用额外的方法重载。”这些“额外”方法根本不会以任何方式“加载”单个数组实例。单个数组实例只有它们自己的属性,“额外”方法位于它们后面的原型上。在每个对象的基础上,它们的相关成本为零。^这就是为什么使用
    Array()
    作为“源”基本上是一个好主意。扩展它(如果必须的话),而不是试图复制函数。好吧,这完全不是一种简单的方法,但无论如何,答案满足了这个问题。@MadBrozzeR:Re-simplicity:完全正确。:-)只使用数组要好得多。@T.J.Crowder就像我之前说过的,我现在这样做的方式(在我的js库中,不在这里)非常类似于“使用实际的数组,并将自定义方法混合到每个数组实例中”,但没有额外的对象:
    var arr=NLtoARR(NodeList)
    arr.Nprops=1
    arr.Nmeths=function(){return}
    返回arr我来这里是为了寻求更好的解决方案。所以,我想,我现在更喜欢这个。非常感谢。答案被接受。只需检查
    new Array()
    new ArrayLike()
    (自定义对象)之间的性能。第一个要快得多。
    function extend(target) {
        var arg, obj, key;
        for (arg = 1; arg < arguments.length; ++arg) {
            obj = arguments[arg];
            for (key in obj) {
                if (obj.hasOwnProperty(key)) {
                    target[key] = obj[key];
                }
            }
        }
        return target;
    }
    
    var a = createArray(['one', 'two', 'three']);