Eu observei isso no Firefox-3.5.7 / Firebug-1.5.3 e Firefox-3.6.16 / Firebug-1.6.2
Quando eu inicio o Firebug:
var x = new Array(3)
console.log(x)
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y)
// [undefined, undefined, undefined]
console.log( x.constructor == y.constructor) // true
console.log(
x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
y.map(function() { return 0; })
)
// [0, 0, 0]
O que está acontecendo aqui? Isso é um bug ou estou entendendo mal como usar new Array(3)
?
javascript
arrays
map-function
rampion
fonte
fonte
var y = x.map(function(){return 0; });
e o recebo tanto no novo método Array () quanto no literal da matriz. Eu testei no Firefox 4 e Chrome.Respostas:
Parece que o primeiro exemplo
Cria uma matriz com ponteiros indefinidos.
E o segundo cria uma matriz com ponteiros para 3 objetos indefinidos; nesse caso, os ponteiros não são indefinidos, apenas os objetos para os quais apontam.
Como o mapa é executado no contexto dos objetos na matriz, acredito que o primeiro mapa não consiga executar a função, enquanto o segundo consegue executar.
fonte
map
chama uma função de retorno de chamada fornecida uma vez para cada elemento de uma matriz, em ordem e constrói uma nova matriz a partir dos resultados.callback
É invocada apenas para índices da matriz que possuem valores atribuídos ; não é invocada para índices que foram excluídos ou aos quais nunca foram atribuídos valores ". Nesse caso,x
os valores de não atribuíram valores explicitamente, enquantoy
os foram atribuídos, mesmo que fosse o valorundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
menos quehasOwnProperty
ele tenha um bug:(new Array(1)).hasOwnProperty(0) === false
e[undefined].hasOwnProperty(0) === true
. De fato, você pode fazer exatamente o mesmo comin
:0 in [undefined] === true
e0 in new Array(0) === false
.x = new Array(3);
é equivalente ax = [,,,];
, nãox = [undefined, undefined, undefined]
.Eu tinha uma tarefa que sabia apenas o comprimento da matriz e precisava transformar os itens. Eu queria fazer algo assim:
Para criar rapidamente uma matriz como esta:
Mas não funcionou porque: (veja a resposta de Jonathan Lonowski, algumas respostas acima)
A solução poderia ser preencher os itens da matriz com qualquer valor (mesmo com indefinido) usando Array.prototype.fill ()
Mostrar snippet de código
Atualizar
Outra solução poderia ser:
fonte
undefined
no.fill()
método, simplificar o código muito ligeiramente paralet arr = new Array(10).fill().map((val,idx) => idx);
Array.from(Array(10))
Com o ES6, você pode fazer
[...Array(10)].map((a, b) => a)
, rápido e fácil!fonte
new Array(10).fill()
. Mesmo resultado que[...Array(10)]
[...Array(10).keys()]
Solução ES6:
Não funciona no texto datilografado (2.3), embora
fonte
Array(10).fill("").map( ...
é o que funcionou para mim com Typescript 2.9As matrizes são diferentes. A diferença é que
new Array(3)
cria uma matriz com um comprimento de três, mas sem propriedades, enquanto[undefined, undefined, undefined]
cria uma matriz com um comprimento de três e três propriedades chamadas "0", "1" e "2", cada uma com um valor deundefined
. Você pode ver a diferença usando oin
operador:Isso decorre do fato levemente confuso de que, se você tentar obter o valor de uma propriedade inexistente de qualquer objeto nativo em JavaScript, ele retornará
undefined
(em vez de gerar um erro, como acontece quando você tenta se referir a uma variável inexistente ), que é o mesmo que você obtém se a propriedade tiver sido explicitamente definida comoundefined
.fonte
Na página MDC para
map
:[undefined]
na verdade se aplica a levantadora no índice (es) de modo quemap
irá iterar, enquantonew Array(1)
apenas inicializa o índice (es) com um valor padrão deundefined
modomap
ignora-lo.Eu acredito que isso é o mesmo para todos os métodos de iteração .
fonte
Na especificação da 6ª edição do ECMAScript.
new Array(3)
apenas define propriedadelength
e não define propriedades de índice como{length: 3}
. consulte https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len Etapa 9.[undefined, undefined, undefined]
irá definir propriedades de índice e propriedades de comprimento como{0: undefined, 1: undefined, 2: undefined, length: 3}
. consulte https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
Etapa 5.métodos
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
da matriz irá verificar a propriedade índice peloHasProperty
método interno, entãonew Array(3).map(v => 1)
não irá invocar o retorno de chamada.para obter mais detalhes, consulte https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
Como consertar?
fonte
Eu acho que a melhor maneira de explicar isso é olhar para a maneira como o Chrome lida com isso.
Então, o que realmente está acontecendo é que o novo Array () está retornando um array vazio com um comprimento de 3, mas sem valores. Portanto, quando você executa
x.map
em uma matriz tecnicamente vazia, não há nada a ser definido.O Firefox apenas 'preenche' esses slots vazios
undefined
mesmo que não tenha valores.Eu não acho que isso seja explicitamente um bug, apenas uma maneira pobre de representar o que está acontecendo. Suponho que o Chrome seja "mais correto" porque mostra que não há realmente nada na matriz.
fonte
Apenas corri para isso. Com certeza seria conveniente poder usar
Array(n).map
.Array(3)
produz aproximadamente{length: 3}
[undefined, undefined, undefined]
cria as propriedades numeradas:{0: undefined, 1: undefined, 2: undefined, length: 3}
.A implementação map () atua apenas nas propriedades definidas.
fonte
Não é um bug. É assim que o construtor Array é definido para funcionar.
Do MDC:
O
.map()
método inclui apenas nos elementos de iteração da matriz que explicitamente tiveram valores atribuídos. Mesmo uma atribuição explícita deundefined
fará com que um valor seja considerado elegível para inclusão na iteração. Isso parece estranho, mas é essencialmente a diferença entre umaundefined
propriedade explícita em um objeto e uma propriedade ausente:O objeto
x
não possui uma propriedade chamada "z" e o objetoy
possui. No entanto, nos dois casos, parece que o "valor" da propriedade éundefined
. Em uma matriz, a situação é semelhante: o valor delength
realiza implicitamente uma atribuição de valor a todos os elementos de zero a zerolength - 1
. A.map()
função, portanto, não fará nada (não chamará o retorno de chamada) quando chamada em uma matriz recém-construída com o construtor Array e um argumento numérico.fonte
undefined
para sempre?x = []
vez dex = new Array()
Se você está fazendo isso para preencher facilmente uma matriz com valores, não pode usar o preenchimento por razões de suporte ao navegador e realmente não deseja executar um loop for, também pode fazer
x = new Array(3).join(".").split(".").map(...
que fornecerá uma matriz de dados vazios cordas.Bastante feio, devo dizer, mas pelo menos o problema e a intenção são claramente comunicados.
fonte
Como a pergunta é por que, isso tem a ver com a forma como o JS foi projetado.
Existem 2 razões principais em que posso pensar para explicar esse comportamento:
Desempenho: fornecido
x = 10000
enew Array(x)
é aconselhável que o construtor evite o loop de 0 a 10000 para preencher a matriz comundefined
valores.Implicitamente "indefinido": Dê
a = [undefined, undefined]
eb = new Array(2)
,a[1]
eb[1]
irão devolverundefined
, masa[8]
eb[8]
também retornaráundefined
mesmo se eles estão fora de alcance.Por fim, a notação
empty x 3
é um atalho para evitar a configuração e a exibição de uma longa lista deundefined
valores que sãoundefined
assim mesmo porque não são declarados explicitamente.Nota: Dada a matriz
a = [0]
ea[9] = 9
,console.log(a)
retornará(10) [0, empty x 8, 9]
, preenchendo a lacuna automaticamente retornando a diferença entre os dois valores declarados explicitamente.fonte
Por motivos detalhados em outras respostas,
Array(n).map
não funciona. No entanto, no ES2015Array.from
aceita uma função de mapa:fonte
Aqui está um método utilitário simples como solução alternativa:
MapFor simples
Exemplo completo
Aqui está um exemplo mais completo (com verificações de integridade) que também permite especificar um índice inicial opcional:
Contagem decrescente
A manipulação do índice passado para o retorno de chamada permite a contagem inversa:
fonte