O que .map () está fazendo nesta situação?

95

Usando o console do Chrome, esta é minha entrada e saída:

[0].map(Array);

[[0, 0, [0]]]; // output

O que esta acontecendo aqui?

EDITAR

Isso me deixa curioso porque algo como

[0].map(String);

Retornará

["0"];

E não

["0", "0", "String"]
Jacksonkr
fonte
34
Presumo que seja porque ele sempre precisa de alguns WTFs de Javascript para se sentir feliz
npst
12
Oh, é apenas uma variante menos wtf-y de['10', '10', '10'].map(parseInt)
gronostaj
2
Outro .map()comportamento estranho : stackoverflow.com/questions/14528397/… Em geral, você deve ter cuidado ao usar .map()com funções que usam mais de um argumento.
Barmar de
2
Just do[0].map(console.log)
Bergi
1
@Jacksonkr: Obrigado pela resposta. Acho que foi assim: Escrevi um comentário, explicando que ver JS WTFs me deixa feliz por não ter que usar a linguagem com frequência. Alguém perguntou por que eu examinaria as perguntas de JS se não gosto da linguagem. npst respondeu e os primeiros dois comentários foram excluídos. É engraçado que seu comentário ainda seja votado, sim.
Eric Duminil de

Respostas:

123

A .map()função está chamando a Array()função com três argumentos, o valor do elemento da matriz, que é 0, o índice desse elemento, também 0, e uma referência a toda a matriz.

Então é como fazer isso:

var a = [0];
var index = 0
Array(a[index], index, a);   // create array with three elements

A matriz retornada por Array()then torna-se o primeiro elemento da matriz que .map()cria, portanto, o nível extra de aninhamento em seu [[0, 0, [0]]]resultado.

EDIT com relação à sua edição: quando você diz [0].map(String);que resulta em String()ser chamado com os mesmos três argumentos como String(a[index], index, a), mas a String()função ignora todos, exceto o primeiro argumento, enquanto Array()usa todos os argumentos fornecidos.

nnnnnn
fonte
39

Em primeiro lugar , Arraypode ser usado como uma função para criar matrizes:

var arr = Array(1, 2, "Hello");

console.log(arr); // [1, 2, "Hello"]

Em segundo lugar , mappassa três parâmetros para seu retorno de chamada: o elemento, seu índice do array e o próprio array.

Portanto , como sua matriz contém um elemento, a linha:

[0].map(Array);

é equivalente a:

[Array(0, 0, [0])];     // the element 0 in the original array will be mapped into Array(0, 0, [0])
ibrahim mahrir
fonte
6

Depois de atualizar a pergunta. Outras respostas fornecem informações sobre o mapa

Para responder por que array e string são diferentes, olhe para os construtores

Construtor de string aceita 1 parâmetro String (coisa) enquanto array new Array (element0, element1 [, ... [, elementN]])

Volodymyr Bilyachat
fonte
2
É a mesma razão pela qual .map(Number)converte cada item em um número, em vez de retornar algo como [3, 2, [4, 1, 3]]para cada item.
user4642212
@Xufox sim, a resposta está nos construtores :)
Volodymyr Bilyachat
4

Esta chamada

[0].map(Array);

fornece o mesmo resultado como se você escrevesse algo assim:

[0].map(function (value, index, array) {
    return Array(value, index, array);
})

A função Map está chamando a função Array com três parâmetros: valor do elemento, índice do elemento e array inteiro. Esta chamada para Arrayretorna o array com 3 elementos: valor (número 0), índice (número 0), array inteiro ( [0]).

E esse novo array é empacotado no Array original, porque você combinou o elemento original (número 0) com o novo elemento (array de 3 elementos)

Nota: Você pode estar acostumado a usar apenas o primeiro parâmetro como em

array.map(function (a) { return a * a; });

ou usando apenas dois para obter também o índice

array.map(function (item, index) { return "index=" + index + ", value=" + item; });

Mas você precisa se lembrar que mapainda fornece 3 parâmetros, você apenas os ignora em sua função de retorno de chamada. Esse também é o motivo pelo qual códigos como:

[0].map(String);

retorna

["0"]

É porque a função String se preocupa apenas com o primeiro parâmetro e ignora outros parâmetros passados. Se você ligar

String(11, "Some", "other", "ignored", "parameters")

você ainda vai conseguir

"11"
Mariusz Pawelski
fonte