jQuery / Método / .slice() - Selecionar um intervalo de índices

No jQuery, .slice(start, end) retorna um novo objeto jQuery para um intervalo da coleção atual, incluindo start e excluindo end. Os índices começam em zero; omitir end seleciona até o último elemento. Os outros elementos não são excluídos da coleção original nem do documento.

Ler intervalos e índices negativos

Os índices da API de .slice() pertencem à coleção atual, não às posições de irmãos em um pai HTML. Alpha, Beta, Gamma, Delta, Epsilon e Zeta ocupam 0 a 5. Valores negativos contam do final; -1 é a última posição.

Chamada Resultado entre seis itens Motivo
.slice(1, 4) Beta, Gamma, Delta Inclui 1, exclui 4
.slice(2) Gamma a Zeta Fim omitido
.slice(-2) Epsilon, Zeta Penúltimo até o final
.slice(1, -1) Beta a Epsilon Para antes do último
.slice(3, 3), .slice(4, 2) Coleção vazia Sem intervalo para a frente

end não é uma quantidade: .slice(1, 4) escolhe três posições, 1, 2 e 3. Use .eq(index) para um único item. .filter() escolhe por condições, não por intervalo contínuo.

Exemplo completo de intervalos e ordem de filtros

Salve todo o código em UTF-8 como slice-demo.html e abra no navegador. É preciso Internet para o arquivo oficial do jQuery 4.0.0 da rede de distribuição de conteúdo (CDN), sem instalação. Intervalos, filtros, adições, restauração e trechos do Console foram executados com 3.7.1 e 4.0.0.

eligible marca itens que atendem à condição do exemplo. Os seis itens iniciais continuam no documento e apenas a seleção é destacada em turquesa.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Select a range from a collection</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button, select { font: inherit; margin: 4px; max-width: 100%; }
    li { border: 1px solid #aab; padding: 8px; margin: 4px; }
    .picked { background: #d9f4ef; border-color: teal; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>Select a collection range</h1>
  <label for="mode">Range:</label>
  <select id="mode">
    <option value="middle">slice(1, 4)</option>
    <option value="last">slice(-2)</option>
    <option value="inner">slice(1, -1)</option>
    <option value="from">slice(2)</option>
    <option value="filterFirst">filter('.eligible').slice(1, 3)</option>
    <option value="sliceFirst">slice(1, 3).filter('.eligible')</option>
    <option value="empty">slice(4, 2)</option>
  </select>
  <button type="button" id="add">Add Eta</button>
  <button type="button" id="reset">Reset</button>
  <ul id="items">
    <li class="eligible" data-name="Alpha">Alpha (eligible)</li>
    <li data-name="Beta">Beta</li>
    <li class="eligible" data-name="Gamma">Gamma (eligible)</li>
    <li data-name="Delta">Delta</li>
    <li class="eligible" data-name="Epsilon">Epsilon (eligible)</li>
    <li class="eligible" data-name="Zeta">Zeta (eligible)</li>
  </ul>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      const initial = $("#items").html();
      function report() {
        const $all = $("#items > li");
        let $selected;
        switch ($("#mode").val()) {
          case "last": $selected = $all.slice(-2); break;
          case "inner": $selected = $all.slice(1, -1); break;
          case "from": $selected = $all.slice(2); break;
          case "filterFirst": $selected = $all.filter(".eligible").slice(1, 3); break;
          case "sliceFirst": $selected = $all.slice(1, 3).filter(".eligible"); break;
          case "empty": $selected = $all.slice(4, 2); break;
          default: $selected = $all.slice(1, 4);
        }
        $all.removeClass("picked");
        $selected.addClass("picked");
        const names = $selected.map(function () { return this.dataset.name; }).get();
        $("#result").text(`source=${$all.length}\nselected=${$selected.length}: ${names.join(", ") || "(none)"}\nDOM items=${$("#items > li").length}`);
      }
      $("#mode").on("change", report);
      $("#add").on("click", function () {
        if (!$("#eta").length) $("#items").append('<li id="eta" class="eligible" data-name="Eta">Eta (eligible)</li>');
        report();
      });
      $("#reset").on("click", function () { $("#items").html(initial); $("#mode").val("middle"); report(); });
      report();
    });
  </script>
</body>
</html>

Inicialmente .slice(1, 4) escolhe três itens. source e DOM items continuam seis.

source=6
selected=3: Beta, Gamma, Delta
DOM items=6
  1. slice(-2) destaca Epsilon e Zeta; slice(1, -1) Beta, Gamma, Delta e Epsilon. Restaure e altere uma condição por vez.
  2. filter('.eligible').slice(1, 3) primeiro reduz para Alpha, Gamma, Epsilon e Zeta e depois escolhe 1 e 2: Gamma e Epsilon.
  3. slice(1, 3).filter('.eligible') primeiro escolhe Beta e Gamma e depois mantém Gamma. A coleção anterior muda a referência dos índices.
  4. slice(4, 2) retorna zero itens sem excluir os seis originais.
  5. Com slice(-2), pressione Add Eta: Zeta e Eta são selecionados porque report() seleciona novamente os sete. Adições duplicadas são impedidas.
  6. Reset restaura lista e modo .slice(1, 4).

Guardar const $last = $("#items > li").slice(-2) não atualiza a seleção após adições. Ela continua apontando para Epsilon e Zeta. Selecione novamente após mudanças no modelo de objetos do documento (DOM) para obter o intervalo atual.

Conferir limites e calcular páginas

Após Reset, execute isto no Console das ferramentas do desenvolvedor. Limites excessivos são ajustados ao comprimento disponível; início depois do final retorna vazio. A última linha confirma que os nós são as mesmas referências, não cópias.

const $items = $("#items > li");
const names = $set => $set.map(function () { return this.dataset.name; }).get().join(",");
console.log(`slice(1,4)=${names($items.slice(1, 4))}`);
console.log(`slice(-2)=${names($items.slice(-2))}`);
console.log(`slice(1,-1)=${names($items.slice(1, -1))}`);
console.log(`equal bounds=${$items.slice(3, 3).length}; beyond end=${$items.slice(10).length}`);
console.log(`clamped range=${$items.slice(-99, 99).length}; original=${$items.length}`);
console.log(`same node=${$items.slice(1, 2).get(0) === $items.get(1)}`);
slice(1,4)=Beta,Gamma,Delta
slice(-2)=Epsilon,Zeta
slice(1,-1)=Beta,Gamma,Delta,Epsilon
equal bounds=0; beyond end=0
clamped range=6; original=6
same node=true

Para páginas a partir de um e tamanho inteiro positivo, start=(page - 1) × pageSize e end=start + pageSize. Este trecho seleciona dois itens da segunda página. Valide antes: uma página negativa poderia virar um índice contado do final.

const page = 2;
const pageSize = 2;
if (!Number.isInteger(page) || page < 1 || !Number.isInteger(pageSize) || pageSize < 1) {
  throw new RangeError("Use positive integer page and pageSize");
}
const start = (page - 1) * pageSize;
const $pageItems = $("#items > li").slice(start, start + pageSize);
console.log(`page=${page}: ${$pageItems.map(function () { return this.dataset.name; }).get().join(",")}`);
page=2: Gamma,Delta

O código calcula uma seleção, sem ocultar outros itens nem buscar dados do servidor. Navegação real exige gestão separada de exibição, total e página atual. Dividir itens já carregados não reduz sozinho trabalho no servidor ou volume baixado.

Investigar itens inesperados

Confira primeiro .length e a ordem atual. Um seletor mais restrito ou .filter() anterior muda a coleção de referência. Não confunda índices com posições CSS de irmãos ou numeração a partir de um. Para incluir o último índice desejado, passe esse índice mais um como end.

slice não clona, move nem exclui nós. Mas .addClass() ou .text() no resultado altera os nós reais compartilhados. Use clonagem explícita se precisar de nós independentes. Mesmo vazio, um objeto jQuery é verdadeiro em uma condição: confira .length em vez do valor booleano do objeto.