代码之家  ›  专栏  ›  技术社区  ›  jon

Javascript错误?indexOf(void 0)返回-1?[复制]

  •  0
  • jon  · 技术社区  · 7 年前

    也就是说,如果我使用当前时间作为数组的索引:

    array[Date.getTime()] = value;
    

    解释器会实例化从0到现在的所有元素吗?不同的浏览器有不同的做法吗?

    我记得以前 AIX 内核,它将根据请求创建伪tty,但如果您这样做了,请说“echo>/dev/pty100000000”,它将创建/dev/pty0,/dev/pty1。。。。然后倒下死去。在贸易展上很有趣,但我不想让这种事发生在我的顾客身上。

    0 回复  |  直到 8 年前
        1
  •  40
  •   Community Mohan Dere    8 年前

    您将不得不询问对具体实现有更多了解的人来回答是什么触发了从密集到稀疏的转换,但是您的示例应该是完全安全的。如果你想得到一个密集数组,你应该用一个显式的长度参数来调用构造函数,希望你能得到一个。

    看到了吗 this answer 更详细的描述。

        2
  •  71
  •   John Kugelman Michael Hodel    16 年前

    是的,是的。它们实际上是内部的哈希表,因此您不仅可以使用大整数,还可以使用字符串、浮点或其他对象。所有键通过 toString() 在被添加到哈希之前。您可以用一些测试代码来确认:

    <script>
      var array = [];
      array[0] = "zero";
      array[new Date().getTime()] = "now";
      array[3.14] = "pi";
    
      for (var i in array) {
          alert("array["+i+"] = " + array[i] + ", typeof("+i+") == " + typeof(i));
      }
    </script>
    

    显示:

    array[0] = zero, typeof(0) == string
    array[1254503972355] = now, typeof(1254503972355) == string
    array[3.14] = pi, typeof(3.14) == string
    

    for...in 语法,它只提供实际定义的索引。如果你用更常见的 for (var i = 0; i < array.length; ++i)

        3
  •  10
  •   John Fisher    16 年前

    您可以通过使用为这类事情设计的javascript语法来避免这个问题。你可以把它当作一本字典,但是“for…”。。。在…“语法可以让你把它们都抓到。

    var sparse = {}; // not []
    sparse["whatever"] = "something";
    
        4
  •  7
  •   Justin Love    16 年前

    Javascript对象是稀疏的,数组只是具有自动维护的length属性的专用对象(实际上比最大索引大一个, 定义元素的数量)和一些附加方法。无论哪种方法都是安全的;如果需要数组的额外特性,请使用数组,否则使用对象。

        5
  •  6
  •   Charles Merriam    6 年前

    内存使用没有定义,任何实现都是愚蠢的。理论上讲, const a = []; a[1000000]=0; 可能会消耗兆字节的内存 const a = [];

    Justin Love 指出,length属性是 最高

    所以,数组是稀疏的。但是像reduce()这样的内置函数,数学.max(),和“为了。。。“将遍历从0到长度的所有可能的整数索引,访问许多返回“未定义”的索引。但是因为。。。in'循环可能如您所期望的那样,只访问已定义的键。

    下面是一个使用节点.js:

    "use strict";
    const print = console.log;
    
    let a = [0, 10];
    // a[2] and a[3] skipped
    a[4] = 40;
    a[5] = undefined;  // which counts towards setting the length
    a[31.4] = 'ten pi';  // doesn't count towards setting the length
    a['pi'] = 3.14;
    print(`a.length= :${a.length}:, a = :${a}:`);
    print(`Math.max(...a) = :${Math.max(a)}: because of 'undefined values'`);
    for (let v of a) print(`v of a; v=:${v}:`);
    for (let i in a) print(`i in a; i=:${i}: a[i]=${a[i]}`);
    

    给:

    a.length= :6:, a = :0,10,,,40,:
    Math.max(...a) = :NaN: because of 'undefined values'
    v of a; v=:0:
    v of a; v=:10:
    v of a; v=:undefined:
    v of a; v=:undefined:
    v of a; v=:40:
    v of a; v=:undefined:
    i in a; i=:0: a[i]=0
    i in a; i=:1: a[i]=10
    i in a; i=:4: a[i]=40
    i in a; i=:5: a[i]=undefined
    i in a; i=:31.4: a[i]=ten pi
    i in a; i=:pi: a[i]=3.14
    

        6
  •  2
  •   pzrq    5 年前

    对于非标准的nodej,稀疏性(或稠密性)可以从经验上得到证实 process.memoryUsage() .

    有时节点足够聪明,可以保持数组稀疏:

    Welcome to Node.js v12.15.0.
    Type ".help" for more information.
    > console.log(`The script is using approximately ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100} MB`)
    The script is using approximately 3.07 MB
    undefined
    > array = []
    []
    > array[2**24] = 2**24
    16777216
    > array
    [ <16777216 empty items>, 16777216 ]
    > console.log(`The script is using approximately ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100} MB`)
    The script is using approximately 2.8 MB
    undefined
    

    有时节点会选择使其密集(这种行为将来可能会得到优化):

    > otherArray = Array(2**24)
    [ <16777216 empty items> ]
    > console.log(`The script is using approximately ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100} MB`)
    The script is using approximately 130.57 MB
    undefined
    

    > yetAnotherArray = Array(2**32-1)
    [ <4294967295 empty items> ]
    > console.log(`The script is using approximately ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100} MB`)
    The script is using approximately 130.68 MB
    undefined
    

    因此,使用密集数组来了解最初的AIX内核错误可能需要使用一个 range-alike :

    > denseArray = [...Array(2**24).keys()]
    [
       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
      12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
      24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
      36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
      60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
      72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
      84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
      96, 97, 98, 99,
      ... 16777116 more items
    ]
    > console.log(`The script is using approximately ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100} MB`);
    The script is using approximately 819.94 MB
    undefined
    

    > tooDenseArray = [...Array(2**32-1).keys()]
    
    <--- Last few GCs --->
    
    [60109:0x1028ca000]   171407 ms: Scavenge 1072.7 (1090.0) -> 1056.7 (1090.0) MB, 0.2 / 0.0 ms  (average mu = 0.968, current mu = 0.832) allocation failure 
    [60109:0x1028ca000]   171420 ms: Scavenge 1072.7 (1090.0) -> 1056.7 (1090.0) MB, 0.2 / 0.0 ms  (average mu = 0.968, current mu = 0.832) allocation failure 
    [60109:0x1028ca000]   171434 ms: Scavenge 1072.7 (1090.0) -> 1056.7 (1090.0) MB, 0.2 / 0.0 ms  (average mu = 0.968, current mu = 0.832) allocation failure 
    
    
    <--- JS stacktrace --->
    
    ==== JS stack trace =========================================
    
        0: ExitFrame [pc: 0x100931399]
        1: StubFrame [pc: 0x1008ee227]
        2: StubFrame [pc: 0x100996051]
    Security context: 0x1043830808a1 <JSObject>
        3: /* anonymous */ [0x1043830b6919] [repl:1] [bytecode=0x1043830b6841 offset=28](this=0x104306fc2261 <JSGlobal Object>)
        4: InternalFrame [pc: 0x1008aefdd]
        5: EntryFrame [pc: 0x1008aedb8]
        6: builtin exit frame: runInThisContext(this=0x104387b8cac1 <ContextifyScript map = 0x1043...
    
    FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory
    
    Writing Node.js report to file: report.20200220.220620.60109.0.001.json
    Node.js report completed
     1: 0x10007f4b9 node::Abort() [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     2: 0x10007f63d node::OnFatalError(char const*, char const*) [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     3: 0x100176a27 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     4: 0x1001769c3 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     5: 0x1002fab75 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     6: 0x1005f3e9b v8::internal::Runtime_FatalProcessOutOfMemoryInvalidArrayLength(int, unsigned long*, v8::internal::Isolate*) [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     7: 0x100931399 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
     8: 0x1008ee227 Builtins_IterableToList [/Users/pzrq/.nvm/versions/node/v12.15.0/bin/node]
    Abort trap: 6
    
        7
  •  1
  •   dkloke    6 年前

    他们可以,但他们不一定总是这样,他们可以表现得更好,当他们不是。

    下面讨论如何在数组实例中测试索引稀疏性: https://benmccormick.org/2018/06/19/code-golf-sparse-arrays/

    此代码高尔夫(最少字符)赢家是:

    let isSparse = a => !!a.reduce(x=>x-1,a.length)
    

    基本上是遍历索引项的数组,同时减少长度值并返回硬化的 !! 假/真数值结果的布尔值(如果累加器一直递减到零,则索引将完全填充,而不是稀疏的)。 Charles Merriam 上面的警告也应该考虑在内,这段代码并没有解决这些问题,但是它们适用于散列字符串条目,当使用 arr[var]= (something) 其中var不是整数。

    What’s the difference between "Array()" and "[]" while declaring a JavaScript array?

    最近对这篇文章的一个回答是关于V8如何通过标记数组以避免(重新)测试稀疏性之类的特性来深入研究V8如何优化数组: https://v8.dev/blog/elements-kinds . 这篇博文是从9月17日开始的,内容可能会有一些变化,但是对日常发展的影响的分解是有用的和清晰的。