【问题标题】:Add a property to a JavaScript array将属性添加到 JavaScript 数组
【发布时间】:2012-03-31 01:07:51
【问题描述】:

默认情况下,数组有一个“长度”属性。

我可以向它们添加自定义属性吗?

不必使它们成为对象。

【问题讨论】:

  • “添加自定义属性而不必使其成为对象是什么意思?” 数组是对象。 JS 中几乎所有的东西都是一个对象。这些属性是什么?你能进一步解释一下吗?
  • 它们对象。只是一种特殊的物体。例如,像函数一样,它们也是一种特殊的对象。
  • 另请参阅this related question,了解为什么不应该这样做。

标签: javascript arrays


【解决方案1】:

当然。

var arr = [1,2,3,4,5];
arr.prop = 'value';

数组是 已经 JavaScript 中的对象——它们只是有一些额外的功能和特殊的文字语法。

【讨论】:

  • 我的属性会与其余元素一起迭代吗?因为在 console.log 中,我看不到它带有像“length”这样的不透明文本
  • 当你使用for(var key in arr)时它们会被迭代。但无论如何,这是你不应该在数组上使用的东西,所以这对你来说应该不是问题。 for(var i = 0; i < arr.length; i++) 迭代不会包含这些属性(它们甚至不会添加到数组的长度中)
  • 如果您使用for in 循环,该属性将被迭代。在常规的for 循环中,它不会——因为您只能通过数组索引访问每个成员。它也不会被原生数组 ES5 方法(如 forEach)迭代。
  • 以上都是真的。例如,stringName.match(/regex/) 返回一个数组,但是该数组还附加了两个额外的属性供您参考 - “返回的数组有一个额外的输入属性,其中包含已解析的原始字符串。此外,它还有一个index 属性,表示字符串中匹配项的从零开始的索引。"但是,当您迭代返回的内容时,或者当您 console.log 结果时,结果集不包含额外的属性,仅包含数组本身的元素。
  • console.log 将显示属性,如果您只想访问属性。你可以做keys = Object.keys(arr).slice(arr.length);。然后您可以使用for in 注意 仅迭代键,但是当您将属性分配给数组时,您应该避免仅使用Numbers,因为它们将被解释为数组索引。 IE。 (如果您的对象继承自 Arrayarr['7'] 将与 arr[7] 混淆)
【解决方案2】:

正如其他答案所说,这是完全可能的,因为 JavaScript 中的数组只是对象。但是,这仍然是一个好主意的问题。

这是一个“编码风格”问题,因此很难客观地说,但 Douglas Crockford 对此没有意见(至少在某些情况下)。在JavaScript: The Good Parts中,他实际上使用了在数组中添加“total”方法的例子。

因为数组实际上是一个对象,我们可以直接向单个数组添加方法:

// Give the data array a total function

data.total = function () {
    return this.reduce(add, 0);
};

total = data.total();    // total is 108

由于字符串'total' 不是整数,将total 属性添加到数组不会改变其长度。

(p62,Crockford 的“JavaScript The Good Parts”,在 Google Books 上找到)

但是,值得一提的是,这些额外的属性不包含在 JSON 序列化中,如果您执行arr = arr.slice(1); 之类的操作,它们将被丢弃。

【讨论】:

  • 感谢您提供参考资料。
  • 另外,如果数组通过它的任何原型方法(map、filter 等),则属性不会被转移到新数组,因为该方法被放在 @ 的实例上987654328@。可能是预期的,但在这种情况下可能不理想?
  • 内置的RegExp.prototype.exec() 返回这样的数组。试试<someRegExp>.exec(<someString>),你会得到一个类似[<fullResult>, <subStrResults>, ..., index: <Number>, input: <origStr>]的数组。见MDN
【解决方案3】:

如果您打算将其隐藏在数组等中(至少这就是我想要的):

Object.defineProperty( targ, "myVal", { enumerable: false, writable: true } );

然后数组不会将它添加到长度,所以它是一个属性,而不是我猜你可以说的值。

然后,如果您想查看对象中的键,Object.keys 不会看到它,但 Reflect.ownKeys() 会。

reflect 版本的defineProperty 会返回成功或失败,而Object 的则返回传递的对象。

记住 Reflect.preventExtensions() 会(就像它说的那样)阻止你或其他人扩展它们。

【讨论】:

    【解决方案4】:

    数组是对象,因此您可以为它们添加自己的属性:

    var arr = [1, 2, 3];
    arr.foo = 'bar';
    

    从其他答案扩展,这里有以下迭代数组的方法,不包括自定义属性。

    1. 使用标准的for循环

       for (let i = 0; i < arr_length; i++)
           console.log(arr[i]);
      

      或者如果不使用 ES6:

       for (var i = 0; i < arr.length; i++)
           console.log(arr[i]);
      
    2. 使用for ... of 循环(ES6+)

       for (let el of arr)
           console.log(el)
      
    3. 使用Array.prototype.forEach (ES6+)

       arr.forEach(el => console.log(el));
      

       arr.forEach(function(el) {
           console.log(el);
       });
      

    遍历数组,包括所有属性(例如,自定义属性,length):

    for (let prop in arr)
        console.log(prop);
    

    或者如果不使用 ES6:

    for (var prop in arr)
        console.log(prop);
    

    【讨论】:

      【解决方案5】:

      是的。您可以通过声明它们将它们添加到对象中,也可以使用 Array.prototype 扩展 Array

      var j = new Array();
      j.yourprop = "foo";
      

      【讨论】:

      • 我更喜欢var j = (function(array){return new array();}(window.Array))
      • 我更喜欢 var j = function(array){return new array();}(window.Array) 给我的 () 键更多寿命
      猜你喜欢
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 2021-12-07
      • 2013-04-25
      • 1970-01-01
      相关资源
      最近更新 更多