Eu sei que é usado para transformar argumentos em uma matriz real, mas não entendo o que acontece ao usar Array.prototype.slice.call(arguments)
474
Eu sei que é usado para transformar argumentos em uma matriz real, mas não entendo o que acontece ao usar Array.prototype.slice.call(arguments)
Respostas:
O que acontece sob o capô é que, quando
.slice()
é chamado normalmente,this
é uma matriz e, em seguida, itera sobre essa matriz e faz seu trabalho.Como está
this
a.slice()
função uma matriz? Porque quando você faz:...
object
automaticamente se torna o valor dethis
emmethod()
. Então com:... a
[1,2,3]
matriz é definida como o valor dethis
in.slice()
.Mas e se você pudesse substituir outra coisa como
this
valor? Desde que o que você substitua tenha uma.length
propriedade numérica e várias propriedades que são índices numéricos, ele deve funcionar. Esse tipo de objeto geralmente é chamado de objeto de matriz .Os métodos
.call()
e.apply()
permitem definir manualmente o valor dethis
em uma função. Então, se nós definir o valorthis
no.slice()
a um array como objeto ,.slice()
só vai assumir que está trabalhando com uma matriz, e vai fazer a sua coisa.Tome esse objeto simples como exemplo.
Obviamente, isso não é uma matriz, mas se você pode defini-la como o
this
valor de.slice()
, funcionará apenas porque parece suficiente com uma matriz para.slice()
funcionar corretamente.Exemplo: http://jsfiddle.net/wSvkv/
Como você pode ver no console, o resultado é o que esperamos:
Então é isso que acontece quando você define um
arguments
objeto como othis
valor de.slice()
. Comoarguments
possui uma.length
propriedade e vários índices numéricos,.slice()
o trabalho é realizado como se estivesse trabalhando em uma matriz real.fonte
Array.prototype.slice
descrição do método.for-in
afirmação que não garante a ordem. O algoritmo usado por.slice()
define uma ordem numérica começando0
e terminando (não inclusivo) com o.length
objeto especificado (ou Matriz ou o que for). Portanto, é garantido que o pedido seja consistente em todas as implementações.var obj = {2:"two", 0:"zero", 1: "one"}
. Se usarmosfor-in
para enumerar o objeto, não há garantia de ordem. Mas se usarmosfor
, podemos aplicar manualmente a ordem:for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. Agora sabemos que as propriedades do objeto serão alcançadas na ordem numérica crescente que definimos pelo nossofor
loop. Isso é o que.slice()
faz. Não importa se ele tem uma matriz real. Apenas inicia em0
e acessa propriedades em um loop ascendente.O
arguments
objeto não é realmente uma instância de uma matriz e não possui nenhum dos métodos de matriz. Portanto,arguments.slice(...)
não funcionará porque o objeto de argumentos não possui o método de fatia.As matrizes têm esse método e, como o
arguments
objeto é muito semelhante a uma matriz, as duas são compatíveis. Isso significa que podemos usar métodos de matriz com o objeto de argumentos. E como os métodos de matriz foram criados com matrizes em mente, eles retornarão matrizes em vez de outros objetos de argumento.Então, por que usar
Array.prototype
? OArray
é o objeto do qual criamos novas matrizes a partir de (new Array()
), e essas novas matrizes passam métodos e propriedades, como fatia. Esses métodos são armazenados no[Class].prototype
objeto. Portanto, por questões de eficiência, em vez de acessar o método de fatia por(new Array()).slice.call()
ou[].slice.call()
, apenas obtemos isso diretamente do protótipo. Isso é para que não tenhamos que inicializar uma nova matriz.Mas por que temos que fazer isso em primeiro lugar? Bem, como você disse, ele converte um objeto de argumentos em uma instância Array. A razão pela qual usamos fatia, no entanto, é mais um "hack" do que qualquer coisa. O método de fatia terá uma fatia de uma matriz, você adivinhou, e retornará essa fatia como uma nova matriz. Não passar argumentos para ele (além do objeto de argumentos como seu contexto) faz com que o método de fatia pegue uma parte completa da "matriz" passada (nesse caso, o objeto de argumentos) e a retorne como uma nova matriz.
fonte
Normalmente, chamando
copiará a matriz
a
parab
. No entanto, não podemos fazerporque
arguments
não é uma matriz real e não temslice
como método.Array.prototype.slice
é aslice
função para matrizes ecall
executa a função comthis
definido comoarguments
.fonte
prototype
? não éslice
umArray
método nativo ?Array
é uma função construtora e a "classe" correspondente éArray.prototype
. Você também pode usar[].slice
slice
é um método de cadaArray
instância, mas não aArray
função construtora. Você usaprototype
para acessar métodos das instâncias teóricas de um construtor.Primeiro, você deve ler como a chamada de função funciona em JavaScript . Eu suspeito que só isso é suficiente para responder à sua pergunta. Mas aqui está um resumo do que está acontecendo:
Array.prototype.slice
extrai o método a partir do protótipo . Mas chamá-lo diretamente não funcionará, pois é um método (não uma função) e, portanto, requer um contexto (um objeto que chama ), caso contrário, seria possível .slice
Array
this
Uncaught TypeError: Array.prototype.slice called on null or undefined
O
call()
método permite especificar o contexto de um método, basicamente tornando essas duas chamadas equivalentes:Exceto que o primeiro requer que o
slice
método exista nasomeObject
cadeia de protótipos do (como faz paraArray
), enquanto o último permite que o contexto (someObject
) seja passado manualmente para o método.Além disso, o último é a abreviação de:
Qual é o mesmo que:
fonte
fonte
Array.prototype.slice.call (argumentos) é a maneira antiquada de converter argumentos em uma matriz.
No ECMAScript 2015, você pode usar Array.from ou o operador de spread:
fonte
É porque, como observa o MDN
Aqui estamos chamando
slice
o objeto nativoArray
e não sua implementação e é por isso que o extra.prototype
fonte
Não se esqueça, que um básico de baixo nível desse comportamento é a conversão de tipo que foi totalmente integrada ao mecanismo JS.
A fatia apenas pega o objeto (graças à propriedade argument.length existente) e retorna o objeto de matriz convertido após fazer todas as operações nele.
A mesma lógica que você pode testar se tentar tratar o método String com um valor INT:
E isso explica a afirmação acima.
fonte
Ele usa o
slice
método que as matrizes têm e o chamathis
sendo oarguments
objeto. Isso significa que ele é chamado como se vocêarguments.slice()
assumisse quearguments
tinha esse método.Criar uma fatia sem argumentos simplesmente usará todos os elementos - portanto, basta copiar os elementos
arguments
para uma matriz.fonte
Vamos supor que você tenha:
function.apply(thisArg, argArray )
O método slice () seleciona uma parte de uma matriz e retorna a nova matriz.
Portanto, quando você chama
Array.prototype.slice.apply(arguments, [0])
o método de fatia da matriz, é invocado (bind) nos argumentos.fonte
Talvez um pouco tarde, mas a resposta para toda essa bagunça é que call () é usado em JS para herança. Se compararmos isso com Python ou PHP, por exemplo, call é usado respectivamente como super (). init () ou parent :: _ construct ().
Este é um exemplo de seu uso que esclarece tudo:
Referência: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
fonte
quando .slice () é chamado normalmente, isso é uma matriz e, em seguida, itera sobre essa matriz e faz seu trabalho.
fonte
Só estou escrevendo isso para me lembrar ...
Ou apenas use esta útil função $ A para transformar a maioria das coisas em uma matriz.
exemplo de uso ...
fonte