Sé que se usa para convertir los argumentos en una matriz real, pero no entiendo qué sucede cuando se usa Array.prototype.slice.call(arguments)
474
Sé que se usa para convertir los argumentos en una matriz real, pero no entiendo qué sucede cuando se usa Array.prototype.slice.call(arguments)
Respuestas:
Lo que sucede debajo del capó es que cuando
.slice()
se llama normalmente,this
es un Array, y luego simplemente itera sobre ese Array, y hace su trabajo.¿Cómo es
this
en la.slice()
función una matriz? Porque cuando lo haces:... el
object
automáticamente se convierte en el valor dethis
en elmethod()
. Entonces con:... la
[1,2,3]
matriz se establece como el valor dethis
in.slice()
.Pero, ¿qué pasaría si pudieras sustituir algo más como
this
valor? Siempre que lo que sustituya tenga una.length
propiedad numérica y un conjunto de propiedades que sean índices numéricos, debería funcionar. Este tipo de objeto a menudo se llama un objeto tipo matriz .El
.call()
y.apply()
métodos le permiten manualmente establece el valor dethis
una función. Así que si nos fijamos el valor dethis
en.slice()
un conjunto similar de objetos ,.slice()
sólo va a suponer que está trabajando con una matriz, y hará su cosa.Tome este objeto simple como ejemplo.
Obviamente, esto no es una matriz, pero si puede establecerlo como el
this
valor de.slice()
, entonces simplemente funcionará, porque se parece lo suficiente a una matriz para.slice()
que funcione correctamente.Ejemplo: http://jsfiddle.net/wSvkv/
Como puede ver en la consola, el resultado es lo que esperamos:
Entonces, esto es lo que sucede cuando configura un
arguments
objeto como elthis
valor de.slice()
. Debido a quearguments
tiene una.length
propiedad y un montón de índices numéricos,.slice()
simplemente realiza su trabajo como si estuviera trabajando en una matriz real.fuente
Array.prototype.slice
descripción del método.for-in
declaración que no garantiza el orden. El algoritmo utilizado por.slice()
define un orden numérico que comienza0
y termina (no incluye) con el.length
del objeto dado (o Array o lo que sea). Por lo tanto, se garantiza que el orden será coherente en todas las implementaciones.var obj = {2:"two", 0:"zero", 1: "one"}
. Si usamosfor-in
para enumerar el objeto, no hay garantía de orden. Pero si utilizamosfor
, podemos cumplir manualmente el orden:for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. Ahora sabemos que las propiedades del objeto se alcanzarán en el orden numérico ascendente que definimos por nuestrofor
bucle. Eso es lo que.slice()
hace. No le importa si tiene una matriz real. Simplemente comienza en0
y accede a las propiedades en un bucle ascendente.El
arguments
objeto no es en realidad una instancia de una matriz y no tiene ninguno de los métodos de matriz. Por lo tanto,arguments.slice(...)
no funcionará porque el objeto de argumentos no tiene el método de división.Las matrices tienen este método, y debido a que el
arguments
objeto es muy similar a una matriz, los dos son compatibles. Esto significa que podemos usar métodos de matriz con el objeto de argumentos. Y dado que los métodos de matriz se construyeron teniendo en cuenta las matrices, devolverán matrices en lugar de otros objetos de argumento.Entonces, ¿por qué usar
Array.prototype
? ElArray
es el objeto desde el que creamos nuevas matrices (new Array()
), y estas nuevas matrices son métodos y propiedades pasados, como el corte. Estos métodos se almacenan en el[Class].prototype
objeto. Entonces, en aras de la eficiencia, en lugar de acceder al método de corte por(new Array()).slice.call()
o[].slice.call()
, simplemente lo obtenemos directamente del prototipo. Esto es para que no tengamos que inicializar una nueva matriz.Pero, ¿por qué tenemos que hacer esto en primer lugar? Bueno, como dijiste, convierte un objeto de argumentos en una instancia de Array. Sin embargo, la razón por la que usamos slice es más un "hack" que cualquier otra cosa. El método de división tomará una, usted lo adivinó, una división de una matriz y devolverá esa división como una nueva matriz. Al no pasarle argumentos (además del objeto de argumentos como contexto), el método de división toma una parte completa de la "matriz" pasada (en este caso, el objeto de argumentos) y la devuelve como una nueva matriz.
fuente
Normalmente, llamando
copiará la matriz
a
enb
. Sin embargo, no podemos hacerporque
arguments
no es una matriz real, y no tieneslice
como método.Array.prototype.slice
es laslice
función para matrices ycall
ejecuta la función conthis
set toarguments
.fuente
prototype
? No esslice
unArray
método nativo ?Array
es una función constructora, y la "clase" correspondiente esArray.prototype
. También puede usar[].slice
slice
es un método de cadaArray
instancia, pero no laArray
función constructora. Se utilizaprototype
para acceder a métodos de instancias teóricas de un constructor.Primero, debe leer cómo funciona la invocación de funciones en JavaScript . Sospecho que solo es suficiente para responder a su pregunta. Pero aquí hay un resumen de lo que está sucediendo:
Array.prototype.slice
extrae el método de 's prototipo . Pero llamarlo directamente no funcionará, ya que es un método (no una función) y, por lo tanto, requiere un contexto (un objeto de llamada ), de lo contrario, arrojaría .slice
Array
this
Uncaught TypeError: Array.prototype.slice called on null or undefined
El
call()
método le permite especificar el contexto de un método, básicamente haciendo que estas dos llamadas sean equivalentes:Excepto que el primero requiere que el
slice
método exista ensomeObject
la cadena de prototipos (como lo hace paraArray
), mientras que el segundo permite que el contexto (someObject
) se pase manualmente al método.Además, este último es la abreviatura de:
Que es lo mismo que:
fuente
fuente
Array.prototype.slice.call (argumentos) es la forma tradicional de convertir un argumento en una matriz.
En ECMAScript 2015, puede usar Array.from o el operador de propagación:
fuente
Es porque, como señala MDN
Aquí estamos llamando
slice
al objeto nativoArray
y no a su implementación y es por eso que el extra.prototype
fuente
No olvide, que los conceptos básicos de bajo nivel de este comportamiento es la conversión de tipos que se integró completamente en el motor JS.
Slice solo toma el objeto (gracias a la propiedad argumentos.length existente) y devuelve el objeto matriz arrojado después de hacer todas las operaciones sobre eso.
Las mismas lógicas que puedes probar si intentas tratar el método String con un valor INT:
Y eso explica la declaración anterior.
fuente
Utiliza el
slice
método que tienen las matrices y lo llamathis
siendo suarguments
objeto. Esto significa que lo llama como siarguments.slice()
supusieras que tuvierasarguments
tal método.Crear un segmento sin argumentos simplemente tomará todos los elementos, por lo que simplemente copia los elementos de
arguments
una matriz.fuente
Asumamos que tienes:
function.apply(thisArg, argArray )
El método slice () selecciona una parte de una matriz y devuelve la nueva matriz.
Entonces, cuando llama
Array.prototype.slice.apply(arguments, [0])
al método de división de matriz, se invoca (enlaza) en los argumentos.fuente
Tal vez un poco tarde, pero la respuesta a todo este desastre es que call () se usa en JS por herencia. Si comparamos esto con Python o PHP, por ejemplo, call se usa respectivamente como super (). init () o parent :: _ construct ().
Este es un ejemplo de su uso que aclara todo:
Referencia: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
fuente
cuando .slice () se llama normalmente, este es un Array, y luego simplemente itera sobre ese Array, y hace su trabajo.
fuente
Solo estoy escribiendo esto para recordarme ...
O simplemente use esta práctica función $ A para convertir la mayoría de las cosas en una matriz.
ejemplo de uso ...
fuente