eliminar elemento delete array actualizar javascript prototype-programming

javascript - elemento - ¿Cómo funciona Array.prototype.slice.call()?



replace array javascript (13)

Sé que se usa para hacer que los argumentos sean una matriz real, pero no entiendo qué sucede cuando uso Array.prototype.slice.call(arguments)


Array.prototype.slice.call (argumentos) es la manera anticuada de convertir un argumento en una matriz.

En ECMAScript 2015, puede usar Array.from o el operador de propagación:

let args = Array.from(arguments); let args = [...arguments];


El objeto de arguments no es realmente una instancia de un Array y no tiene ninguno de los métodos de Array. Por lo tanto, los arguments.slice(...) no funcionarán porque el objeto de argumentos no tiene el método de división.

Las matrices tienen este método, y debido a que el objeto de arguments 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 crearon teniendo en cuenta las matrices, devolverán matrices en lugar de otros objetos de argumento.

Entonces, ¿por qué usar Array.prototype ? El Array es el objeto desde el cual creamos nuevos arreglos ( new Array() ), y estos nuevos arreglos pasan métodos y propiedades, como slice. Estos métodos se almacenan en el objeto [Class].prototype . Entonces, por razones de eficiencia, en lugar de acceder al método slice por (new Array()).slice.call() o [].slice.call() , 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. La razón por la que usamos slice, sin embargo, es más un "hack" que cualquier otra cosa. El método de división tomará, usted lo adivinó, división de una matriz y devolverá esa división como una nueva matriz. Al no pasarle ningún argumento (además del objeto de argumentos como su 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.


Es porque, como señala MDN

El objeto de argumentos no es una matriz. Es similar a una matriz, pero no tiene propiedades de matriz excepto la longitud. Por ejemplo, no tiene el método pop. Sin embargo, se puede convertir a una matriz real:

Aquí estamos invocando el slice en la Array objetos nativos y no en su implementación y por eso el .prototype adicional .prototype

var args = Array.prototype.slice.call(arguments);


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 función .slice() una matriz? Porque cuando lo haces:

object.method();

... el object se convierte automáticamente en el valor de this en el method() . Así que con:

[1,2,3].slice()

... la matriz [1,2,3] se establece como el valor de this en .slice() .

Pero, ¿qué pasaría si pudieras sustituir otra cosa como el valor de this ? Siempre que lo que sustituyas tenga una propiedad numérica .length y un conjunto de propiedades que sean índices numéricos, debería funcionar. Este tipo de objeto a menudo se llama un objeto similar a una matriz .

Los .call() y .apply() permiten establecer manualmente el valor de this en una función. Entonces, si establecemos el valor de this en .slice() en un objeto similar a una matriz , .slice() simplemente asumirá que está funcionando con una matriz, y hará su trabajo.

Tomemos este objeto simple como ejemplo.

var my_object = { ''0'': ''zero'', ''1'': ''one'', ''2'': ''two'', ''3'': ''three'', ''4'': ''four'', length: 5 };

Obviamente, esto no es un Array, pero si puede configurarlo como this valor de .slice() , entonces solo funcionará, porque se parece a un Array para que .slice() funcione correctamente.

var sliced = Array.prototype.slice.call( my_object, 3 );

Ejemplo: http://jsfiddle.net/wSvkv/

Como puede ver en la consola, el resultado es lo que esperamos:

[''three'',''four''];

Entonces, esto es lo que sucede cuando establece un objeto de arguments como el valor de este .slice() . Debido a que los arguments tienen una propiedad .length y un grupo de índices numéricos, .slice() simplemente realiza su trabajo como si estuviera trabajando en una matriz real.


No se olvide, que los conceptos básicos de bajo nivel de este comportamiento es la conversión de tipos que se integra completamente en el motor JS.

Slice solo toma el objeto (gracias a la propiedadargent.length existente) y devuelve el objeto de matriz fundido después de realizar todas las operaciones en eso.

Las mismas lógicas que puede probar si intenta tratar el método de cadena con un valor INT:

String.prototype.bold.call(11); // returns "<b>11</b>"

Y eso explica la afirmación anterior.


Normalmente, llamando

var b = a.slice();

Copiará la matriz a en b . Sin embargo, no podemos hacer

var a = arguments.slice();

porque los arguments no es una matriz real, y no tiene sector como método. Array.prototype.slice es la función de división para matrices, y call ejecuta la función con this conjunto en arguments .


Primero, debes leer cómo funciona la invocación de funciones en JavaScript . Sospecho que solo es suficiente para responder a tu pregunta. Pero aquí hay un resumen de lo que está sucediendo:

Array.prototype.slice extrae el method slice del prototype de Array . Pero llamarlo directamente no funcionará, ya que es un método (no una función) y, por lo tanto, requiere un contexto (un objeto que llama, this ), de lo contrario, arrojaría Uncaught TypeError: Array.prototype.slice called on null or undefined .

El método call() permite especificar el contexto de un método, básicamente haciendo que estas dos llamadas sean equivalentes:

someObject.slice(1, 2); slice.call(someObject, 1, 2);

Excepto que el primero requiere que el método de someObject exista en la cadena de prototipo de someObject (como lo hace para Array ), mientras que el segundo permite que el contexto ( someObject ) se pase al método de forma manual.

Además, este último es corto para:

var slice = Array.prototype.slice; slice.call(someObject, 1, 2);

Que es lo mismo que:

Array.prototype.slice.call(someObject, 1, 2);


Solo estoy escribiendo esto para recordarme ...

Array.prototype.slice.call(arguments); == Array.prototype.slice(arguments[1], arguments[2], arguments[3], ...) == [ arguments[1], arguments[2], arguments[3], ... ]

O simplemente use esta función práctica $ A para convertir la mayoría de las cosas en una matriz.

function hasArrayNature(a) { return !!a && (typeof a == "object" || typeof a == "function") && "length" in a && !("setInterval" in a) && (Object.prototype.toString.call(a) === "[object Array]" || "callee" in a || "item" in a); } function $A(b) { if (!hasArrayNature(b)) return [ b ]; if (b.item) { var a = b.length, c = new Array(a); while (a--) c[a] = b[a]; return c; } return Array.prototype.slice.call(b); }

ejemplo de uso ...

function test() { $A( arguments ).forEach( function(arg) { console.log("Argument: " + arg); }); }


Supongamos que tiene: function.apply(thisArg, argArray )

El método de aplicación invoca una función, pasando el objeto que se vinculará a esta y una matriz opcional de argumentos.

El método slice () selecciona una parte de una matriz y devuelve la nueva matriz.

Entonces, cuando llama a Array.prototype.slice.apply(arguments, [0]) , se invoca el método de división de matriz (vinculación) en los argumentos.


Tal vez un poco tarde, pero la respuesta a todo este lío es que call () se usa en JS para herencia. Si comparamos esto con Python o PHP, por ejemplo, la llamada se usa respectivamente como super (). init () o parent :: _ construct ().

Este es un ejemplo de su uso que aclara todo:

function Teacher(first, last, age, gender, interests, subject) { Person.call(this, first, last, age, gender, interests); this.subject = subject; }

Referencia: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance


Utiliza el método de división que tienen las matrices y lo llama, siendo this el objeto de arguments . Esto significa que lo llama como si hiciera arguments.slice() asumiendo que los arguments tenían tal método.

Crear una división sin ningún argumento simplemente tomará todos los elementos, así que simplemente copia los elementos de los arguments a una matriz.


cuando .slice () se llama normalmente, esto es un Array, y luego simplemente itera sobre ese Array, y hace su trabajo.

//ARGUMENTS function func(){ console.log(arguments);//[1, 2, 3, 4] //var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function var arrArguments = [].slice.call(arguments);//cp array with explicity THIS arrArguments.push(''new''); console.log(arrArguments) } func(1,2,3,4)//[1, 2, 3, 4, "new"]


// We can apply `slice` from `Array.prototype`: Array.prototype.slice.call([]); //-> [] // Since `slice` is available on an array''s prototype chain, ''slice'' in []; //-> true [].slice === Array.prototype.slice; //-> true // … we can just invoke it directly: [].slice(); //-> [] // `arguments` has no `slice` method ''slice'' in arguments; //-> false // … but we can apply it the same way: Array.prototype.slice.call(arguments); //-> […] // In fact, though `slice` belongs to `Array.prototype`, // it can operate on any array-like object: Array.prototype.slice.call({0: 1, length: 1}); //-> [1]