Ou seja, se eu usar a hora atual como um índice na matriz:
array[Date.getTime()] = value;
o interpretador instanciará todos os elementos de 0 até agora? Navegadores diferentes fazem isso de maneira diferente?
Lembro que costumava haver um bug no kernel AIX , que criava pseudo-ttys a pedido, mas se você fizesse, digamos, "echo> / dev / pty10000000000", ele criaria / dev / pty0, / dev / pty1, .... e então cair morto. Era divertido em feiras, mas não quero que isso aconteça com meus clientes.
javascript
sparse-matrix
baga
fonte
fonte
Respostas:
Como exatamente as matrizes de JavaScript são implementadas difere de navegador para navegador, mas geralmente recorrem a uma implementação esparsa - provavelmente a mesma usada para acesso de propriedade de objetos regulares - se usar uma matriz real seria ineficiente.
Você terá que perguntar a alguém com mais conhecimento sobre implementações específicas para responder o que exatamente desencadeia a mudança de denso para esparso, mas seu exemplo deve ser perfeitamente seguro. Se você deseja obter uma matriz densa, deve chamar o construtor com um argumento de comprimento explícito e esperar que realmente obtenha um.
Veja esta resposta para uma descrição mais detalhada de olliej.
fonte
foo = new Array(10000)
. No entanto, este é suposto trabalho:foo = Array.apply(null, {length: 10});
.Sim, eles estão. Na verdade, elas são tabelas hash internamente, portanto, você pode usar não apenas números inteiros grandes, mas também strings, flutuantes ou outros objetos. Todas as chaves são convertidas em strings
toString()
antes de serem adicionadas ao hash. Você pode confirmar isso com algum código de teste:Monitores:
Observe como usei a
for...in
sintaxe, que fornece apenas os índices que estão realmente definidos. Se você usar ofor (var i = 0; i < array.length; ++i)
estilo mais comum de iteração, obviamente terá problemas com índices de array não padrão.fonte
length
propriedade mágicalength
só é invisível emfor..in
loops porque tem oDontEnum
sinalizador definido; no ES5, o atributo de propriedade é chamadoenumerable
e pode ser explicitamente definido viaObject.defineProperty()
String
; qualquer outra coisa que você colocar no subscrito serátoString()
-ed. Combine isso com a imprecisão de inteiro de grande número e isso significa que se você definira[9999999999999999]=1
,a[10000000000000000]
será 1 (e muitos outros comportamentos surpreendentes). Usar números não inteiros como chaves é muito imprudente e objetos arbitrários estão fora de questão.Você pode evitar o problema usando uma sintaxe javascript projetada para esse tipo de coisa. Você pode tratá-lo como um dicionário, mas a sintaxe "para ... em ..." permitirá que você pegue todos eles.
fonte
Os objetos Javascript são esparsos e os arrays são apenas objetos especializados com uma propriedade de comprimento mantida automaticamente (que na verdade é maior que o maior índice, não o número de elementos definidos) e alguns métodos adicionais. Você está seguro de qualquer maneira; use um array se precisar de seus recursos extras e um objeto caso contrário.
fonte
A resposta, como geralmente é verdade com JavaScript, é "é um pouco mais estranho ..."
O uso de memória não é definido e qualquer implementação pode ser estúpida. Em teoria,
const a = []; a[1000000]=0;
poderia queimar megabytes de memória, como poderiaconst a = [];
. Na prática, até a Microsoft evita essas implementações.Justin Love aponta que o atributo de comprimento é o conjunto de índice mais alto . MAS só é atualizado se o índice for um inteiro.
Portanto, a matriz é esparsa. MAS funções embutidas como reduzir (), Math.max () e "for ... of" percorrerão toda a gama de índices inteiros possíveis de 0 até o comprimento, visitando muitos que retornam 'indefinido'. MAS 'for ... in' loops podem fazer o que você espera, visitando apenas as chaves definidas.
Aqui está um exemplo usando Node.js:
dando:
Mas. Existem mais casos esquivos com Arrays ainda não mencionados.
fonte
A escassez (ou densidade) pode ser confirmada empiricamente para NodeJS com o não padrão process.memoryUsage () .
Às vezes, o node é inteligente o suficiente para manter o array esparso:
Às vezes, o nó opta por torná-lo denso (esse comportamento pode muito bem ser otimizado no futuro):
Em seguida, esparso novamente:
Portanto, talvez o uso de uma matriz densa para ter uma ideia do bug do kernel AIX original precise ser forçado com um intervalo semelhante :
Porque por que não fazer cair?
fonte
Eles podem ser, mas nem sempre precisam ser, e podem ter um desempenho melhor quando não o são.
Aqui está uma discussão sobre como testar a dispersão do índice em uma instância de array: https://benmccormick.org/2018/06/19/code-golf-sparse-arrays/
O vencedor deste código de golfe (menos caracteres) é:
Basicamente percorrer a matriz para entradas indexadas enquanto diminui o valor do comprimento e retorna o
!!
booleano endurecido do resultado numérico falso / verdadeiro (se o acumulador for decrementado até zero, o índice é totalmente preenchido e não esparso). As advertências de Charles Merriam acima também devem ser consideradas e este código não as aborda, mas elas se aplicam a entradas de string com hash que podem acontecer ao atribuir elementosarr[var]= (something)
onde var não é um inteiro.Um motivo para se preocupar com a dispersão do índice são seus efeitos no desempenho, que podem diferir entre os mecanismos de script, há uma grande discussão sobre criação / inicialização de array: Qual é a diferença entre "Array ()" e "[]" ao declarar um JavaScript matriz?
Uma resposta recente a essa postagem tem um link para este mergulho profundo em como o V8 tenta otimizar arrays marcando-os para evitar (re) testes de características como dispersão: https://v8.dev/blog/elements-kinds . A postagem do blog é de setembro de 17 e o material está sujeito a algumas alterações, mas a análise das implicações para o desenvolvimento do dia-a-dia é útil e clara.
fonte