jQuery / Method / .slice() - 일치하는 요소의 일부분만 선택하는 메서드
jQuery의 .slice(start, end)는 현재 jQuery 집합에서 start 인덱스는 포함하고 end 인덱스는 제외한 구간을 새 jQuery 객체로 반환합니다. 인덱스는 0부터 시작하며 end를 생략하면 마지막까지 선택합니다. 원래 집합이나 문서에서 나머지 요소를 삭제하는 메서드는 아닙니다.
구간과 음수 인덱스 읽기
.slice() 공식 문서의 인덱스는 HTML 부모 아래의 형제 순번이 아니라 현재 선택 집합의 순서입니다. 여섯 요소가 Alpha·Beta·Gamma·Delta·Epsilon·Zeta 순서라면 인덱스는 각각 0·1·2·3·4·5입니다. 음수는 끝에서 거슬러 센 위치이며 -1은 마지막 요소 위치입니다.
| 호출 | 여섯 요소에서의 결과 | 이유 |
|---|---|---|
| .slice(1, 4) | Beta·Gamma·Delta | 1 포함, 4 제외 |
| .slice(2) | Gamma부터 Zeta까지 | 끝 생략 |
| .slice(-2) | Epsilon·Zeta | 뒤에서 두 번째부터 끝까지 |
| .slice(1, -1) | Beta부터 Epsilon까지 | 마지막 위치를 끝으로 삼되 제외 |
| .slice(3, 3)·.slice(4, 2) | 빈 집합 | 포함할 앞쪽 구간이 없음 |
끝 숫자는 선택할 개수가 아닙니다. .slice(1, 4)는 4개가 아니라 인덱스 1·2·3의 3개입니다. 한 요소만 고를 때는 .eq(index)도 사용할 수 있으며, 조건에 맞는 요소를 고르는 .filter()와는 기준이 다릅니다.
범위와 필터 순서를 비교하는 전체 예제
전체 코드를 UTF-8로 slice-demo.html에 저장하고 브라우저로 엽니다. 콘텐츠 전송망(CDN)의 공식 jQuery 파일 4.0.0을 읽으므로 인터넷 연결이 필요하며 설치는 없습니다. 범위 선택, 필터 순서, 추가·초기화와 콘솔 코드를 3.7.1·4.0.0에서 실행해 확인했습니다.
eligible은 조건에 맞는 항목을 표시하는 예제용 클래스입니다. 출발 목록은 여섯 개이고, 현재 구간만 청록색으로 강조합니다. 화면에 보이는 나머지 항목도 문서에 그대로 남습니다.
<!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>
처음에는 .slice(1, 4)의 세 항목이 선택됩니다. source와 DOM items는 모두 6으로 유지됩니다.
source=6
selected=3: Beta, Gamma, Delta
DOM items=6
- slice(-2)는 Epsilon·Zeta, slice(1, -1)는 Beta·Gamma·Delta·Epsilon을 강조합니다. Reset 후 한 조건씩 바꿔 확인합니다.
- filter('.eligible').slice(1, 3)는 먼저 Alpha·Gamma·Epsilon·Zeta로 줄인 다음 그 집합의 1·2인 Gamma·Epsilon을 고릅니다.
- slice(1, 3).filter('.eligible')는 먼저 원본의 Beta·Gamma를 고른 뒤 조건을 적용해 Gamma만 남깁니다. 같은 숫자라도 앞선 집합이 달라 결과가 다릅니다.
- slice(4, 2)는 결과 0개이며 원본 여섯 개는 삭제되지 않습니다.
- slice(-2) 상태에서 Add Eta를 누르면 Zeta·Eta가 선택됩니다. report()가 일곱 항목을 새로 선택하기 때문입니다. 중복 추가는 막습니다.
- Reset은 원래 목록과 .slice(1, 4) 모드로 돌아갑니다.
기존 const $last = $("#items > li").slice(-2)가 나중의 추가에 맞춰 자동으로 마지막 두 항목으로 바뀌는 것은 아닙니다. 저장한 결과는 당시의 Epsilon·Zeta 노드를 계속 가리킵니다. 현재 구간이 필요하면 DOM(Document Object Model, 문서 객체 모델)이 바뀐 뒤 다시 선택합니다.
빈 범위·경계와 페이지 구간 확인하기
Reset 후 개발자 도구 Console에서 다음 코드를 실행합니다. 범위가 너무 크면 가능한 길이 안으로 조정되고, 시작이 끝을 벗어나면 빈 결과입니다. 새 jQuery 집합이어도 안의 DOM 노드는 복사본이 아니라 원본과 같은 참조라는 점을 마지막 줄에서 확인합니다.
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
페이지 번호를 1부터, 페이지 크기를 양의 정수로 정하면 시작은 (page - 1) × pageSize, 끝은 start + pageSize입니다. 아래 코드는 같은 페이지 Console에서 두 번째 구간의 두 항목만 선택합니다. 잘못된 음수 페이지를 그대로 넣으면 .slice()의 뒤쪽 인덱스로 해석될 수 있어 먼저 검증합니다.
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
이 코드는 구간을 계산할 뿐 다른 항목을 숨기거나 서버에서 새 자료를 가져오지 않습니다. 실제 화면의 페이지 전환은 표시할 항목·전체 수·현재 페이지 관리가 별도로 필요합니다. 이미 문서에 들어온 전체 항목을 잘랐다는 이유로 서버 페이지 처리나 데이터 다운로드 양이 줄었다고 설명하지 않습니다.
예상과 다른 항목이 선택될 때
먼저 .length와 현재 집합의 순서를 확인합니다. 좁힌 선택자나 .filter()를 앞에 두면 숫자의 기준도 좁힌 집합이 됩니다. 형제 순번용 CSS 선택자와 혼동하거나 인덱스를 1부터 세지 않습니다. 끝을 포함하고 싶다면 필요한 마지막 인덱스보다 1 큰 값을 end로 전달합니다.
.slice()는 선택 결과를 만들며 노드 복제·이동·삭제를 하지 않습니다. 그러나 결과에 .addClass()·.text() 등을 적용하면 공유하는 실제 노드가 바뀝니다. 독립적인 복제본이 필요할 때는 별도의 복제 동작을 의도적으로 사용합니다. 결과가 비어도 jQuery 객체 자체는 존재하므로 유무는 객체의 참·거짓이 아니라 .length로 확인합니다.




