Programming
Arrays
Code Tutorial
Javascript
Data Structures

How to get first N number of elements from an array

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

In JavaScript, use array.slice(0, n) to get the first N elements from an array. It returns a new array containing the first N items without modifying the original. If N is larger than the array length, slice returns all available elements without throwing an error. This operation is one of the most common array manipulations, and every mainstream language has an equivalent.

Using slice in JavaScript

Array.prototype.slice(start, end) extracts a section of an array and returns it as a new array. The start index is inclusive and the end index is exclusive.

javascript
1const colors = ["red", "green", "blue", "yellow", "purple"];
2const firstThree = colors.slice(0, 3);
3
4console.log(firstThree); // ["red", "green", "blue"]
5console.log(colors);     // ["red", "green", "blue", "yellow", "purple"] (unchanged)

When N Exceeds Array Length

slice does not throw an error. It returns whatever elements are available.

javascript
const items = [1, 2, 3];
console.log(items.slice(0, 100)); // [1, 2, 3]

This means you typically do not need a bounds check before calling slice. The method handles it internally.

When N Is Zero or Negative

javascript
1const items = [1, 2, 3, 4, 5];
2
3console.log(items.slice(0, 0));   // []
4console.log(items.slice(0, -1));  // [1, 2, 3, 4] (negative end counts from the end)

A negative end argument does not mean "first negative-N elements." It means "stop that many positions from the end." This is sometimes useful but often surprising if you expected an empty result.

slice vs splice: A Critical Difference

These two methods have almost identical names but fundamentally different behaviors.

MethodMutates OriginalReturnsUse Case
slice(0, n)NoNew array with first N elementsRead a prefix without changing the source
splice(0, n)YesArray of removed elementsRemove and consume the first N elements
javascript
1// slice: non-destructive
2const a = [10, 20, 30, 40, 50];
3const sliced = a.slice(0, 3);
4console.log(sliced); // [10, 20, 30]
5console.log(a);      // [10, 20, 30, 40, 50] (unchanged)
6
7// splice: destructive
8const b = [10, 20, 30, 40, 50];
9const spliced = b.splice(0, 3);
10console.log(spliced); // [10, 20, 30]
11console.log(b);       // [40, 50] (mutated!)

If your array is shared across multiple functions or stored in a state management system like Redux, using splice when you meant slice creates a mutation bug that can be difficult to trace.

Writing a Reusable Helper

When this operation appears repeatedly in application code, wrapping it in a named function communicates intent more clearly than inline slice calls.

javascript
1function takeFirst(arr, n) {
2  if (!Array.isArray(arr)) {
3    throw new TypeError("Expected an array");
4  }
5  const count = Math.max(0, Math.floor(n));
6  return arr.slice(0, count);
7}
8
9console.log(takeFirst([1, 2, 3, 4, 5], 3));    // [1, 2, 3]
10console.log(takeFirst([1, 2, 3], 10));           // [1, 2, 3]
11console.log(takeFirst([1, 2, 3, 4, 5], -2));     // []
12console.log(takeFirst([1, 2, 3, 4, 5], 2.7));    // [1, 2]

This helper clamps negative values to 0 and floors floating-point numbers, making the boundary behavior explicit.

TypeScript Version

typescript
1function takeFirst<T>(arr: T[], n: number): T[] {
2  const count = Math.max(0, Math.floor(n));
3  return arr.slice(0, count);
4}
5
6const users: string[] = ["Alice", "Bob", "Charlie", "Diana"];
7const topTwo: string[] = takeFirst(users, 2); // ["Alice", "Bob"]

Generics preserve the element type through the function call, so the return type stays string[] rather than collapsing to any[].

Equivalent Operations in Other Languages

Python

Python's slice syntax is concise and handles out-of-bounds gracefully.

python
1values = [10, 20, 30, 40, 50]
2first_three = values[:3]
3print(first_three)  # [10, 20, 30]
4print(values)       # [10, 20, 30, 40, 50] (unchanged)
5
6# N larger than length
7print(values[:100])  # [10, 20, 30, 40, 50]

Java

Java arrays are fixed-size, so prefix extraction creates a new array.

java
1import java.util.Arrays;
2
3public class Main {
4    public static void main(String[] args) {
5        int[] values = {10, 20, 30, 40, 50};
6        int n = 3;
7
8        int[] firstN = Arrays.copyOfRange(values, 0, Math.min(n, values.length));
9        System.out.println(Arrays.toString(firstN)); // [10, 20, 30]
10    }
11}

Unlike JavaScript's slice, Arrays.copyOfRange throws ArrayIndexOutOfBoundsException if the end index exceeds the array length. The Math.min guard is necessary.

For List types, Java offers subList:

java
1import java.util.List;
2
3List<String> names = List.of("Alice", "Bob", "Charlie", "Diana");
4List<String> firstTwo = names.subList(0, Math.min(2, names.size()));
5// ["Alice", "Bob"]

Note that subList returns a view, not a copy. Modifications to the original list affect the sublist.

C++

cpp
1#include <vector>
2#include <algorithm>
3#include <iostream>
4
5int main() {
6    std::vector<int> values = {10, 20, 30, 40, 50};
7    int n = 3;
8
9    std::vector<int> firstN(values.begin(), values.begin() + std::min(n, (int)values.size()));
10
11    for (int v : firstN) {
12        std::cout << v << " ";  // 10 20 30
13    }
14    return 0;
15}

The iterator-range constructor copies elements into a new vector. The std::min prevents advancing the iterator past the end.

Comparison Table

LanguageSyntaxMutates OriginalHandles N > Length
JavaScriptarr.slice(0, n)NoYes, returns all elements
Pythonarr[:n]NoYes, returns all elements
Java (array)Arrays.copyOfRange(arr, 0, n)NoThrows if n > length (use Math.min)
Java (List)list.subList(0, n)Returns a view (not independent)Throws if n > size (use Math.min)
C++vector(begin, begin + n)NoUndefined behavior if n > size (use std::min)
TypeScriptarr.slice(0, n)NoYes, returns all elements

Performance Considerations

slice creates a shallow copy. For arrays of primitive values, this is a memory copy proportional to N. For arrays of objects, the new array holds references to the same objects, not deep copies.

javascript
1const original = [{ name: "Alice" }, { name: "Bob" }];
2const first = original.slice(0, 1);
3
4first[0].name = "Modified";
5console.log(original[0].name); // "Modified" (same reference)

If you need independent copies of the objects, you must deep-clone them separately. slice alone is not enough.

For very large arrays where you only need to iterate over the first N elements (not store them), consider a simple loop instead of creating a new array:

javascript
1const largeArray = new Array(1_000_000).fill(0).map((_, i) => i);
2
3// Creates a 1000-element copy
4const firstThousand = largeArray.slice(0, 1000);
5
6// Alternative: iterate without copying
7for (let i = 0; i < 1000 && i < largeArray.length; i++) {
8  process(largeArray[i]);
9}

Common Pitfalls

  • Using splice instead of slice. This mutates the original array. In state-driven frameworks like React or Redux, this causes bugs because state should be immutable.
  • Assuming the second argument to slice is a count. It is an exclusive end index, not a count. For a prefix starting at 0, the values happen to be the same, but for non-zero start indices they differ.
  • Not handling negative N. JavaScript's slice(0, -3) returns all elements except the last 3, which is rarely the intent when someone passes a "first N" value that happens to be negative.
  • Assuming slice deep-copies objects. It creates a shallow copy. Mutating an object in the sliced array also mutates it in the original.
  • Using Arrays.copyOfRange in Java without bounds checking. Unlike JavaScript, Java throws an exception when the end index exceeds the array length.
  • Calling subList in Java and treating the result as independent. The returned list is a view backed by the original list. Structural modifications to the original list invalidate the sublist.

Summary

  • In JavaScript, array.slice(0, n) is the standard way to get the first N elements. It returns a new array and does not modify the original.
  • splice looks similar but mutates the array. Use slice for reading, splice for consuming and removing.
  • JavaScript and Python handle N > array length gracefully. Java and C++ require explicit bounds checking.
  • slice creates a shallow copy. Object references in the new array still point to the same objects.
  • Wrap the operation in a named helper like takeFirst() when the boundary behavior (negative N, floats) matters to your application logic.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.