Array.prototype.slice()

Este articulo necesita una revisión editorial. Cómo puedes ayudar.

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

El método slice() devuelve una copia de una parte del array dentro de un nuevo array empezando por inicio hasta fin (fin no incluido). El array original no se modificará.

Sintaxis 

arr.slice([inicio [, fin]])

Parámetros

inicio
Índice donde empieza la extracción. El primer elemento corresponde con el índice  0.
Si el índice especificado es negativo, indica un desplazamiento desde el final del array. slice(-2)extrae los dos últimos elementos del array
Si inicio es omitido el valor por defecto es 0.
fin
Índice  que marca el final de la extracción. slice extrae hasta, pero sin incluir el final.
slice(1,4) extrae desde el segundo elemento hasta el cuarto  (los elementos con índices 1, 2,  y 3).
Como un índice negativo, end indica un desplazamiento desde el final de la secuencia. slice(2,-1) extrae desde el tercer hasta el penúltimo elemento en la secuencia.
Si end es omitido, slice extrae hasta el final de la secuencia (arr.length).

Valor return

Un nuevo array con los valores extraídos.

Descripción

El método slice no modifica. Devuelve una copia plana (shallow copy) de los elementos especificados del array original. Los elementos del array original son copiados en el array devuelto de la siguiente manera:

  • Para referencias de objeto ( no el objeto en sí ), slice copia la referencia dentro del nuevo array. Ambos, el array original y el nuevo, referencian al mismo objeto. Si un objeto referenciado cambia, los cambios son visibles para ambos arrays.
  • Para strings y numbers (no los objetos StringNumber), slice copia los strings y numbers en el nuevo array. Los cambios a los string o numbers en un array no afectan a los del otro array.

Si un nuevo elemento es agregado a cualquera de los arrays, el otro array no es afectado.

Ejemplos

Ejemplo: Devolver una porción de un array existente

var nombres = ['Rita', 'Pedro', 'Miguel', 'Ana', 'Vanesa'];
var masculinos = nombres.slice(1, 3);

// masculinos contiene ['Pedro','Miguel']

Ejemplo: Utilizando slice

Presta especial atención a:

  • Valores de tipos básicos, como string o number, son copiados al nuevo array. Cambiar estos valores en la copia no afecta al array original.
  • Las referencias también se copian. Mismas referencias acceden al mismo objeto destino. Cambios en el objeto destino son compartidos por todos sus accesos.
var objeto = { propiedad1: "valor1" }; // se crea un objeto en la memoria dinámica (heap). objeto sirve como acceso
var original = [ objeto, "texto", 4 ]; // nota que objeto es una referencia
var copiaParcial = original.slice(0,2);// se copian los elementos con índice [0] y [1]

copiaParcial[0].propiedad1 = "";       // modificación a través de una referencia.
copiaParcial[1] = 3;                   // modificación directa.
original[0] === copiaParcial[0];       // true, los dos son la misma referencia a un único objeto en memoria.
original[0].propiedad1 === "";         // true, no importa desde qué referencia se modifique. Las dos ven lo mismo.
original[1] === 3;                     // false!!  sigue conservando su valor "texto". copiaParcial modificó diréctamente
                                       // su propiedad, que es muy distinto de modificar un objeto externo accedido a través
                                       // de su propiedad

Objetos array-like

Se dice que un objeto es array-like ( similar o que se asemeja a un array) cuando entre sus propiedades existen algunas cuyos nombres son números y en particular tiene una propiedad llamada length. Este hecho  hace  suponer que el objeto es algún tipo de colección de elementos indexados por números. Es conveniente, a veces, convertir estos objetos a arrays para otorgarles la funcionalidad que de serie se incorpora en todos los arrays a través de su prototipo. 

El método slice puede ser usado para convertir objetos parecidos a arrays o colecciones a un nuevo Array. Simplemente debe enlazar el método al objeto. El  arguments dentro de una función es un ejemplo de un objeto parecido a arrays.

function list() {
  return Array.prototype.slice.call(arguments, 0);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

El enlazado puede realizarse con la función .call de  Function.prototype y puede ser abreviado también usando  [].slice.call(arguments) en lugar de Array.prototype.slice.call. En cualquier caso, puede ser simplificado usando bind.

var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);

function list() {
  return slice(arguments, 0);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

Coordinación del comportamiento entre navegadores

 

La especificación permite a los objetos del host  ( entre ellos los objetos del DOM )  ser dependientes de la implementación.  Esta NO obligatoriedad, origina diferencias en el comportamiento entre aquellos comprometidos con los estándares, como Mozilla, y los que no. En lo que concierne a  Array.prototype.slice , por lo tanto, existen importantes incompatibilidades en IE < 9 . Versiones de IE a partir de la 9 permiten un comportamiento compatible más fiable.  Se puede recurrir al  “shimming”  para alcanzar la compatibilidad en otros casos.  Mientras otros navegadores modernos continúan mejorando para soportar esta habilidad, en la forma en que actualmente lo hacen Mozilla, Chrome, Safari, Opera  e IE, los desarrolladores de código preocupados por el soporte DOM que confíen en este shim no deben dejarse engañar por la semántica, deben confiar de forma segura en ella para proporcionar el comportamiento estándar que aparentemente ahora es la norma.

El shim también soluciona que IE pueda tratar con el caso de que el segundo argumento de slice() pueda ser un valor null/undefined explícito. Esto era un problema en versiones anteriores de IE, pero todos los navegadores modernos, incluído IE >= 9, lo hacen actualmente.

/**
 * Shim para "solucionar" la falta de soporte de IE (IE < 9) para aplicar slice
 * sobre objetos del host, tal como NamedNodeMap, NodeList, y HTMLCollection
 * (técnicamente, al ser los objetos del host dependientes de la implementación,
 * al menos anteriormente a ES6, IE no tenía la necesidad de trabajar de este modo).
 * También funciona sobre strings, solucionando que IE < 9 admita un undefined explícito
 * como segundo argumento (igual que en Firefox), y previniendo errores cuando se llama
 * sobre otros objetos del DOM.
 */
(function () {
  'use strict';
  var _slice = Array.prototype.slice;

  try {
    // Fallará al usarse con elementos DOM en IE < 9
    _slice.call(document.documentElement);
  } catch (e) { // Fails in IE < 9
    // Funcionará con arrays genuinos, objetos array-like, 
    // NamedNodeMap (attributes, entities, notations),
    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
    Array.prototype.slice = function(begin, end) {
      // A IE < 9 no le gustan los undefined como argumento end.
      end = (typeof end !== 'undefined') ? end : this.length;

      // Con objetos Array nativos, podemos usar la función slice
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }

      // Con objetos array-like debemos manejarlo por nuestra cuenta.
      var i, cloned = [],
        size, len = this.length;

      // Maneja valores negativos para el argumento "inicio" 
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);

      // Maneja valores negativos para el argumento "fin"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }

      // Tamaño esperado para el slice
      size = upTo - start;

      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };
  }
}());

Especificaciones

Especificación Estado Observaciones
ECMAScript 3ª edición Estandar Definición inicial Implementado en JavaScript 1.2.
ECMAScript 5.1 (ECMA-262)
The definition of 'Array.prototype.slice' in that specification.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Array.prototype.slice' in that specification.
Standard  

Compatibilidad con navegadores

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Soporte básico 1.0 1.0 (1.7 or earlier) (Yes) (Yes) (Yes)
Feature Android Chrome para Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Soporte básico (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)

Ver también 

Etiquetas y colaboradores del documento

 Colaboradores en esta página: atl3, eljonims, Grijander81, asero82, oillescas
 Última actualización por: atl3,