A maioria dos tutoriais que li sobre matrizes em JavaScript (incluindo w3schools e devguru ) sugerem que você pode inicializar uma matriz com um certo comprimento passando um número inteiro ao construtor Array usando a var test = new Array(4);
sintaxe.
Depois de usar essa sintaxe liberalmente nos meus arquivos js, executei um dos arquivos através do jsLint , e ele se assustou:
Erro: Problema no caractere da linha 1 22: Esperado ')' e viu '4'.
teste var = nova matriz (4);
Problema na linha 1, caractere 23: Esperado ';' e viu ')'.
teste var = nova matriz (4);
Problema no caractere 23 da linha 1: esperava um identificador e viu ')'.
Após ler a explicação do comportamento de jsLint, parece que o jsLint não gosta muito da new Array()
sintaxe e prefere []
ao declarar matrizes.
Então, eu tenho algumas perguntas:
Primeiro porque? Estou correndo algum risco usando a new Array()
sintaxe? Existem incompatibilidades de navegador que eu devo estar ciente?
E segundo, se eu alternar para a sintaxe entre colchetes, existe alguma maneira de declarar uma matriz e definir seu comprimento em uma linha ou preciso fazer algo assim:
var test = [];
test.length = 4;
fonte
new Array()
em geral, mas está tudo bem com a especificação de tamanho. Eu acho que tudo se resume à consistência do código em todo o contexto.Respostas:
Por que você deseja inicializar o comprimento? Teoricamente, não há necessidade disso. Pode até resultar em comportamento confuso, porque todos os testes que usam o
length
para descobrir se uma matriz está vazia ou não relatam que a matriz não está vazia.Alguns testes mostram que definir o comprimento inicial de matrizes grandes pode ser mais eficiente se a matriz for preenchida posteriormente, mas o ganho de desempenho (se houver) parece diferir de navegador para navegador.
O jsLint não gosta
new Array()
porque o construtor é ambíguo.cria uma matriz vazia de comprimento 4. Mas
cria uma matriz contendo o valor
'4'
.Sobre o seu comentário: Em JS, você não precisa inicializar o comprimento da matriz. Cresce dinamicamente. Você pode simplesmente armazenar o comprimento em alguma variável, por exemplo
fonte
for
loop que itera sobre o comprimento da matriz e o preenche. Eu acho que haveria outras maneiras de fazer isso no JavaScript, então a resposta real para "Por que eu quero fazer isso?" é "Por causa de velhos hábitos que se formaram durante a programação em outras linguagens". :)new Array(10)
não cria uma matriz com 10 elementos indefinidos. Ele simplesmente cria uma matriz vazia com um comprimento de 10. Veja esta resposta para a verdade desagradável: stackoverflow.com/questions/18947892/…Array(5)
fornece uma matriz com comprimento 5, mas sem valores; portanto, você não pode iterar sobre ela.Array.apply(null, Array(5)).map(function () {})
fornece uma matriz com comprimento 5 e indefinida como valores, agora pode ser iterada.Array.apply(null, Array(5)).map(function (x, i) { return i; })
fornece uma matriz com comprimento 5 e valores 0,1,2,3,4.Array(5).forEach(alert)
não faz nada,Array.apply(null, Array(5)).forEach(alert)
dá 5 alertasES6
nos dáArray.from
então agora você também pode usarArray.from(Array(5)).forEach(alert)
Se você quiser inicializar com um determinado valor, estes são bons para sabe ...
Array.from('abcde')
,Array.from('x'.repeat(5))
ou
Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
fonte
Array
recebe vários argumentos, itera sobre oarguments
objeto e aplica explicitamente cada valor à nova matriz. Quando você chamaArray.apply
com uma matriz ou um objeto com uma propriedade length,Array
usa o comprimento para definir explicitamente cada valor da nova matriz. É por isso queArray(5)
fornece uma matriz de 5 elisões, enquantoArray.apply(null, Array(5))
fornece uma matriz de 5 não definidas. Para mais informações, consulte esta resposta.Array.apply(null, Array(5))
pode ser escrito comoArray.apply(null, {length: 5})
. Não há realmente muita diferença, mas o último é inequivocamente claro que a intenção é criar uma matriz delength 5
, e não um array contendo5
Com o ES2015,
.fill()
agora você pode simplesmente fazer:O que é muito mais conciso do que
Array.apply(0, new Array(n)).map(i => value)
É possível soltar o
0
in.fill()
e executar sem argumentos, o que preencherá a matrizundefined
. ( No entanto, isso falhará no texto datilografado )fonte
When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
Array(n).fill()
OU
Nota: você não pode repetir slots vazios, ou seja
Array(4).forEach(() => …)
OU
( seguro datilografado )
OU
Método clássico usando uma função (funciona em qualquer navegador)
Criando matrizes aninhadas
Ao criar uma matriz 2D com o
fill
intuitivamente deve criar novas instâncias. Mas o que realmente vai acontecer é o mesmo array que será armazenado como referência.Solução
Portanto, uma matriz 3x2 terá a seguinte aparência:
Matriz N-dimensional
Inicializar um tabuleiro de xadrez
fonte
a[0].push(9);
// [ [6, 9], [6], [6] ]
deve sera[0].push(9);
// [ [6, 9], [6, 9], [6, 9] ]
porque cada matriz aninhada é armazenada como referência, portanto, a mutação de uma matriz afeta o restante. Você pode ter digitado errado, embora eu pense :)O mais curto:
fonte
[
sem usar a,;
pois ele tentará desreferenciar a linha acima. Portanto, uma maneira segura de usar essa linha previsivelmente em qualquer parte do código seria:;[...Array(1000)]//.whateverOpsNeeded()
[...Array(5)].map((item, index) => ({ index }))
tente também:[...Array(5)]; console.log('hello');
const a = 'a'
e a próxima linha[...Array(5)].//irrelevent
. O que você acha que a primeira linha resolveria? Seria oconst a = 'a'[...Array(5)]
que resultaria em:Uncaught SyntaxError: Unexpected token ...
const a = 'a'
haverá um erro de cotão nesse caso. De qualquer forma, realmente não tem nada a ver com esta resposta.O ES6 apresenta o
Array.from
que permite criar um objeto aArray
partir de qualquer objeto "semelhante ao array" ou iterável :Nesse caso,
{length: 10}
representa a definição mínima de um objeto "semelhante a uma matriz" : um objeto vazio com apenas umalength
propriedade definida.Array.from
permite que um segundo argumento seja mapeado sobre a matriz resultante.fonte
Isso inicializará a propriedade length para 4:
fonte
var size = 42; var myArray = eval("["+",".repeat(size)+"]");
? (Não é tão grave;)Estou surpreso que não tenha sido sugerida uma solução funcional que permita definir o comprimento em uma linha. O seguinte é baseado no UnderscoreJS:
Pelas razões mencionadas acima, eu evitaria fazer isso, a menos que desejasse inicializar a matriz com um valor específico. É interessante notar que existem outras bibliotecas que implementam o intervalo, incluindo Lo-dash e Lazy, que podem ter características de desempenho diferentes.
fonte
Por favor, as pessoas ainda não abandonam seus velhos hábitos. Há uma grande diferença na velocidade entre alocar memória e trabalhar com as entradas nessa matriz (como antigamente) e alocá-la várias vezes à medida que uma matriz cresce (o que é inevitavelmente o que o sistema faz sob o capô com outros métodos sugeridos) .
Nada disso é claro, até que você queira fazer algo bacana com matrizes maiores. Então faz.
Visto que ainda parece não haver opção no JS no momento para definir a capacidade inicial de uma matriz, eu uso o seguinte ...
Existem tradeoffs envolvidos:
standard
matriz reserva permanentemente tanto espaço quanto a maior matriz solicitada.Mas se ele se encaixa no que você está fazendo, pode haver uma recompensa. Tempo informal coloca
bem rápido (cerca de 50ms para os 10000, considerando que com n = 1000000 demorou cerca de 5 segundos) e
em mais de um minuto (cerca de 90 segundos para o 10000 no mesmo console cromado ou cerca de 2000 vezes mais lento). Essa não será apenas a alocação, mas também os 10000 toques, para o loop, etc.
fonte
(provavelmente foi melhor como comentário, mas demorou demais)
Então, depois de ler isso, fiquei curioso para saber se a pré-alocação era realmente mais rápida, porque em teoria deveria ser. No entanto, este blog deu algumas dicas desaconselhando http://www.html5rocks.com/en/tutorials/speed/v8/ .
Então, ainda não tenho certeza, coloquei-o à prova. E, como se vê, parece de fato ser mais lento.
Esse código produz o seguinte após algumas execuções casuais:
fonte
fonte
[5: 0]
uma matriz esparsa e provavelmente não é o que se deseja.Aqui está outra solução
O primeiro argumento de
apply()
é uma ligação deste objeto, com a qual não nos importamos aqui, portanto, definimos comonull
.Array.apply(..)
está chamando aArray(..)
função e espalhando o{ length: 3 }
valor do objeto como seus argumentos.fonte
new Array(n)
Isso significa que você não pode usar para inicializar uma matriz como essanew Array(n).map(function(notUsed,index){...})
, mas com essa abordagem, como o @zangw mencionou, você pode fazê-lo. +1 de mim.O construtor do array tem uma sintaxe ambígua , e o JSLint apenas prejudica seus sentimentos, afinal.
Além disso, seu código de exemplo está quebrado, a segunda
var
instrução irá gerar aSyntaxError
. Você está definindo a propriedadelength
da matriztest
, portanto não há necessidade de outravar
.No que diz respeito às suas opções,
array.length
é a única opção "limpa". A pergunta é: por que você precisa definir o tamanho em primeiro lugar? Tente refatorar seu código para se livrar dessa dependência.fonte
var test
. Essa foi uma cópia e colagem desleixada da minha parte.Supondo que o comprimento da matriz seja constante. Em Javascript, é isso que fazemos:
const intialArray = new Array(specify the value);
fonte
Como explicado acima, o uso
new Array(size)
é um pouco perigoso. Em vez de usá-lo diretamente, coloque-o dentro de uma "função criadora de matriz". Você pode facilmente garantir que esta função esteja livre de erros e evite o perigo de ligarnew Array(size)
diretamente. Além disso, você pode atribuir a ele um valor inicial padrão opcional. EstacreateArray
função faz exatamente isso:fonte
Na maioria das respostas, é recomendado para
fill
a matriz porque, caso contrário, "você não pode iterar sobre ela" , mas isso não é verdade. Você pode iterar uma matriz vazia, mas não comforEach
. Loops while, for of loops e for i loops funcionam bem.Não funciona.
Estes trabalhos:
Verifique este violino com os exemplos acima.
Também os angulares
*ngFor
funcionam bem com uma matriz vazia:fonte
Você pode definir o comprimento da matriz usando
array.length = youValue
Então seria
fonte
O motivo pelo qual você não deve usar
new Array
é demonstrado por este código:Algum outro código pode mexer com a variável Array. Eu sei que é um pouco absurdo que alguém escreva esse código, mas ainda assim ...
Além disso, como Felix King disse, a interface é um pouco inconsistente e pode levar a alguns bugs muito difíceis de rastrear.
Se você deseja uma matriz com comprimento = x, preenchida com indefinida (como
new Array(x)
faria), você pode fazer o seguinte:fonte
alert
eundefined
, porque algum outro código pode mexer com eles. O segundo exemplo é menos legível do quenew Array(4)
e não oferece o mesmo resultado: jsfiddle.net/73fKd