completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Slicing, splicing & joining

Copy parts of an array, change arrays in place, join values into strings, split strings back into arrays, and avoid the classic fill and shallow-copy traps.

By the end, you can
  • 01
    Tell copying tools from changing toolsSay whether slice, splice, concat, fill, and copyWithin change the original array, and what each one gives back.
  • 02
    Turn arrays into text and backUse join and split with a separator, with no separator, with empty pieces, and with a limit.
  • 03
    Build new arrays on purposeUse spread, Array.from, and Array.of, and avoid the empty slots of new Array(3) and the shared object of fill({}).

Copy part of a list, change a list, or turn it into text

An array is an ordered list of values. In Array basics you learned to read an item by its index, check the length, and add or remove items. This lesson shows more array tools. Each tool does one of three jobs:

  • It copies part of an array into a new array.
  • It changes the array itself.
  • It turns an array into text, or text into an array.

Two words come up again and again. A copy is a new array, and the original array stays the same. To mutate an array means to change the array itself. Every part of your code that uses that array then sees the change. A method that mutates is said to work in place.

Copy a cart previewPop out in the code editor (opens in a new tab)JavaScript
const cart = ["tea", "bread", "apples"];
const preview = cart.slice(0, 2);
console.log(preview.join(","));
console.log(cart.join(","));

Line 1 makes an array called cart with three items. Line 2 copies the first two items into a new array called preview. Line 3 prints tea,bread. Line 4 prints tea,bread,apples, so the cart still has all three items. The join(",") on lines 3 and 4 turns an array into text with commas between the items. You'll learn it properly later in this lesson.

For every method in this lesson, ask two questions. What does it give back? And does it change the original array?

The table below lists every tool in this lesson. Read each row as: "this tool changes the original array or not, it gives back this, and here is one thing to watch for."

Does each tool change the original array?
ToolDoes it change the original?What does it give back?Watch out for
slice(start, end)No.A shallow copy of some of the items.Objects inside are shared with the original.
splice(start, deleteCount, ...items)Yes.An array of the removed items.Other code that uses the same array sees the change.
concat(...)No.A new shallow array.An array you pass in gets opened one level deep.
join(separator)No.A string.null and undefined become empty text.
split(separator, limit)No. It works on a string, and strings never change.A new array of strings.Empty pieces are kept.
fill(value, start, end)Yes.The same array.An object value is shared by every filled slot.
copyWithin(target, start, end)Yes.The same array.It copies items inside the same array.
Array.from(value, mapFn)No.A new array.Its function can make a new object for each slot.
Copies here are shallow

Spread, slice, and concat make a new outer array. That kind of copy is called shallow: only the outer array is new. If an item is an object or another array, the copy and the original share that same item. You saw why in Objects & references.

This lesson also uses ideas from Strings and Default & rest parameters. A separator is the text placed between items, like a comma. Spread, written ..., opens an array and places its items one by one somewhere else.

slice copies; splice changes the array

INTERACTIVE
Real-life analogyslice is a photocopier; splice is surgery on the book

slice and splice differ by only one letter, so they are easy to mix up. Picture a book. With slice, you photocopy some pages, and the book stays as it was. With splice, you cut pages out of the book itself, and maybe glue new pages in.

In real life: Photocopy pages 2 to 4
In JavaScript: array.slice(1, 4) gives back copies of the items at indexes 1, 2, and 3
In real life: The book stays on the shelf, unchanged
In JavaScript: slice doesn't change the original array
In real life: Cut pages out of the book and glue new pages in
In JavaScript: array.splice(start, deleteCount, ...items) changes the original array
In real life: The pages you cut out land on your desk
In JavaScript: splice gives back an array of the removed items

slice(start, end) copies items into a new array:

  • It starts at index start.
  • It stops just before index end. The item at end is not included.
  • If you leave out end, it copies all the way to the end of the array.
  • A negative index counts from the end. slice(-2) means "the last two items".

splice(start, deleteCount, ...items) changes the array itself:

  • It starts at index start.
  • It removes deleteCount items from there.
  • It puts any items you pass in their place.
  • It gives back a new array that holds the removed items. It does not give back the changed array. Many bugs come from forgetting this.
slice copies one letterPop out in the code editor (opens in a new tab)JavaScript
const letters = ["a", "b", "c"];
const middle = letters.slice(1, 2);
console.log(middle.join(""));
console.log(letters.join(""));

Line 1 makes letters. Line 2 copies from index 1 up to, but not including, index 2. That is just "b". Line 3 prints b. Line 4 prints abc, so slice did not change letters. The join("") puts the letters together with nothing between them.

splice swaps one task for anotherPop out in the code editor (opens in a new tab)JavaScript
const todo = ["write", "test", "ship"];
const removed = todo.splice(1, 1, "review");
console.log(removed[0]);
console.log(todo.join(","));

Line 2 starts at index 1, removes 1 item ("test"), and puts "review" in its place. It gives back ["test"], which is saved in removed. Line 3 prints test. Line 4 prints write,review,ship. Unlike slice, this call changed todo.

Both start with letters holding a, b, c, d. Left: letters.slice(1, 3) returns b and c, and letters still holds a, b, c, d. Right: letters.splice(1, 2) returns b and c, and letters now holds only a and d.letters.slice(1, 3)bcgives backabcdletters afterletters.splice(1, 2)bcgives backadletters after
Both sides start with ["a", "b", "c", "d"] and give back b and c. slice copies them, so letters still has all four letters. splice cuts them out, so letters is left with a and d.
Run slice or splice on the same starting array
The two calls this lab runsPop out in the code editor (opens in a new tab)JavaScript
const letters = ["a", "b", "c", "d"];letters.slice(start, end);letters.splice(start, deleteCount, ...items);
What JavaScript didslice
return value["b","c"]
original after["a","b","c","d"]
abcd
Try it yourself

slice gave back a copy of some items. The original array did not change, even with a negative start.

Each button starts from a fresh array, ["a", "b", "c", "d"], so you can compare the two methods fairly.

Try setting start to -2. Then slice copies from the second-to-last item, and splice starts cutting at the second-to-last item. Each button runs the real method on a fresh array. So the "return value" box shows what the method really gave back, and the "original after" box shows what the array really holds now.

concat and spread: put lists together in a new list

STEP THROUGH
Put two breakfast lists togetherPop out in the code editor (opens in a new tab)JavaScript
const first = ["tea"];
const second = ["bread"];
const breakfast = first.concat(second);
console.log(breakfast.join(","));
console.log(first.join(","));

Line 3 calls first.concat(second). It makes a new array with the items of first, then the items of second. Line 4 prints tea,bread. Line 5 prints tea, so first did not change.

There are two ways to put arrays together without changing them:

  • Spread: [...a, ...b]. Each ... opens one array and places its items inside the new square brackets.
  • concat: a.concat(b, 4). It starts with the items of a, adds the items of b, and then adds the value 4.

Both give back a new outer array.

Real-life analogyconcat and spread are tape

Picture taping two shopping lists onto a new sheet of paper. The old lists still exist. Now say one photo is taped to the old list and to the new sheet. There is still only one photo. If you draw on it, both sheets show the drawing.

In real life: Tape two shopping lists onto a fresh sheet
In JavaScript: [...a, ...b] makes a new outer array
In real life: Write one more item at the bottom
In JavaScript: a.concat(b, 4) can add arrays and single values
In real life: A photo taped to both sheets is the same photo
In JavaScript: An inner array or object in both arrays is shared
Step through concat, spread, and a shallow copy
Step 0 of 8Ready
Your turn: follow the blue line

Guess which arrays change. Then step through spread, concat, and one shallow copy.

Running in
  1. script
Next: line 1
const b = [3];const spread = [...a, ...b];const concatted = a.concat(b, 4);const nested = [["Ada"], ["Lin"]];const copy = nested.slice();copy[0].push("Grace");console.log(JSON.stringify(spread), JSON.stringify(concatted), JSON.stringify(nested[0]));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Lines 3 and 4 hold no surprises. [...a, ...b] gives [1, 2, 3], and a.concat(b, 4) gives [1, 2, 3, 4]. Lines 5 to 7 show the catch. slice, spread, and concat make shallow copies. If an item is an object or an inner array, the copy and the original share it. Line 7 adds "Grace" through copy[0], and nested[0] shows it too.

Two carts, nested and copy, are two separate outer arrays. Each holds a slot [0]. Both slots point to the same inner array, which holds Ada and Grace.["Ada", "Grace"]one inner array[0]nested[0]copy
nested and copy are two different outer arrays. But slot [0] in each one points to the same inner array. So when line 7 adds "Grace" through copy[0], nested[0] shows it too.

join and split: turn arrays into text and back

INTERACTIVE
Turn tags into text to showPop out in the code editor (opens in a new tab)JavaScript
const tags = "js,arrays".split(",");
console.log(tags.join(" | "));

Line 1 cuts the text "js,arrays" at each comma. That gives the array ["js", "arrays"]. Line 2 puts the items back together with " | " between them, and prints js | arrays.

An array with "a", "b", "c". An arrow labeled join("-") goes to the string "a-b-c". An arrow labeled split("-") goes back to the array."a""b""c"arrayjoin("-")split("-")"a-b-c"string
join("-") puts the items into one string, with - between them. split("-") cuts that string at every - and gives back an array.
Real-life analogyjoin threads beads; split cuts the necklace

Think of array items as beads. join threads them onto one string, with a separator between each pair. split does the opposite: it cuts a string wherever it finds the separator.

In real life: Thread beads with a dash between each pair
In JavaScript: ["a", "b", "c"].join("-") gives back "a-b-c"
In real life: No spacer chosen? Put a comma between beads
In JavaScript: join() with no separator puts commas between items
In real life: Cut the necklace at every comma
In JavaScript: "a,b,,c".split(",") gives back four pieces

Here are some checked results from join:

  • ["a", "b", "c"].join("-") gives a-b-c.
  • join() with no separator uses a comma: a,b,c.
  • [null, undefined, 1].join("-") gives --1. null and undefined turn into empty text, but the dashes stay.

And here are some from split:

  • "a,b,,c".split(",") gives ["a","b","","c"]. Two commas in a row have nothing between them, so you get an empty string, "".
  • "a,b,,c".split(",", 2) gives ["a","b"]. The second argument is a limit: the most pieces you want back.
  • "hi".split("") gives ["h","i"]. An empty separator cuts between every character.

Emoji are different. One emoji can come out as more than one piece with split(""). The Unicode & string internals lesson explains why.

Join an array into text, then split text into an array
The two calls this lab runsPop out in the code editor (opens in a new tab)JavaScript
const pieces = ["a", "b", "c"];pieces.join("-");"a,b,,c".split(",");
What JavaScript didseparator ","
["a", "b", "c"].join(...)"a,b,c"
"a,b,,c".split(...)["a","b","","c"]
Try it yourself

join gives back one string. split gives back an array of strings. An empty piece shows up as "".

Try -, a space, and an empty separator. An empty separator works for plain letters. Emoji need the Unicode lesson that comes later.

Array.from and Array.of: build new arrays

STEP THROUGH
Build a short price listPop out in the code editor (opens in a new tab)JavaScript
const prices = Array.from({ length: 3 }, (_, index) => (index + 1) * 10);
console.log(prices.join(","));

Line 1 asks for a new array of length 3. For each index, 0, 1, and 2, the arrow function works out one price: (index + 1) * 10. The function's first argument would be the item. Here every item is undefined, so it gets the name _, which means "not used". Line 2 prints 10,20,30.

Array.from makes a new array from another value. It accepts two kinds of value:

  • An iterable: a value you can loop over one item at a time, such as a string. Array.from("hey") gives ["h", "e", "y"].
  • An array-like object: an object with a length property. Array.from({ length: 3 }, (_, i) => i * 2) gives [0, 2, 4].

A Set is iterable too. A Set is a collection that keeps each value only once. Array.from(new Set([1, 1, 2])) gives [1,2]. The Set dropped the second 1 before Array.from read it. Sets get their own lesson later.

Array.of avoids a surprise you met in Array basics:

  • Array.of(3) makes an array with one item, the number 3: [3].
  • new Array(3) makes an array with length 3 but no items. Its three slots are empty.

This mix-up causes real bugs, so it is worth seeing again.

Build arrays, then spot the fill trap
Step 0 of 8Ready
Your turn: follow the blue line

Pick a length and guess the evens array. Then step through the ways to build arrays and the fill trap.

Running in
  1. script
Next: line 1
const evens = Array.from({ length: 4 }, (_, i) => i * 2);const oneNumber = Array.of(3);const emptySlots = new Array(3);const rows = new Array(3).fill({ done: false });rows[0].done = true;const shifted = [1, 2, 3, 4, 5].copyWithin(0, 3);console.log(letters, evens, oneNumber, emptySlots.length, rows[1].done, shifted);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Change line 2: how long should the evens array be?

Picking a new length runs the code again from the start.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

fill and copyWithin: two tools that change the array

Fill seats with one stringPop out in the code editor (opens in a new tab)JavaScript
const seats = new Array(3).fill("open");
seats[1] = "taken";
console.log(seats.join(","));

Line 1 makes an array with 3 empty slots. Then fill writes "open" into each slot. Line 2 changes slot 1 to "taken". Line 3 prints open,taken,open. This works well because "open" is a string. A string is a primitive value: it has no parts that one slot could change for the others.

Real-life analogyfill paints lockers

fill is handy with primitive values: new Array(3).fill(0) gives [0, 0, 0]. With an object, it is different. fill() does not make a new object for each slot. It puts the same one object in every slot.

In real life: Paint lockers 2 to 5 blue
In JavaScript: array.fill("blue", 1, 5) writes into indexes 1 to 4
In real life: Every locker gets a key to the same storage room
In JavaScript: fill({}) puts the same object in every slot
In real life: Copy the labels from one row of lockers onto another row
In JavaScript: copyWithin copies items to another place in the same array

The step-through above showed this trap. After rows[0].done = true, rows[1].done is true too. All three slots hold the same object.

Left: after fill with an object, slots [0], [1], and [2] all point to one object, so all show done: true. Right: with Array.from, each slot points to its own object, so only slot [0] shows done: true.fill({ done: false })[0][1][2]done: trueone object for allArray.from(…)[0][1][2]done: truedone: falsedone: falseone object each
Both run rows[0].done = true. On the left, fill put one object in all three slots, so every row now says true. On the right, Array.from made a new object for each slot, so only row 0 changes.

The fix is to make a new object for each slot. Array.from calls your function once per slot, so each call makes a new object:

A new object for each rowPop out in the code editor (opens in a new tab)JavaScript
const rows = Array.from({ length: 3 }, () => ({ done: false }));

copyWithin is used less often. It copies some items to another place in the same array, and it changes that array. For example, [1, 2, 3, 4, 5].copyWithin(0, 3) copies the items from index 3 onward, 4 and 5, to index 0. The array becomes [4,5,3,4,5], and the method gives back that same array. You may not write it often. When you read it, remember that it changes the array.

Where you'll use this

Apps keep lists all the time: cart items, chosen filters, open tabs, songs in a playlist, rows in a form, and text a person typed. These tools work on those lists.

Remove one item without changing the originalPop out in the code editor (opens in a new tab)JavaScript
const items = ["red", "green", "blue", "gold"];const index = 1;const next = [...items.slice(0, index), ...items.slice(index + 1)];

Line 3 copies the items before index 1 and the items after index 1. Then it spreads both copies into a new array: ["red", "blue", "gold"]. items still has all four colors, so other code that uses it keeps working. Later, the Sorting & copying safely lesson shows toSpliced, a newer method that does the job of splice without changing the original.

  • Use split to cut text a person typed into tags, and join to show the cleaned tags as text.
  • Use concat or spread to add new results from a server to a list, without changing the old list.
  • Use Array.from to make placeholder rows, with a new object for each row.
  • Use slice to show the first few cards while keeping the full list.
Rules worth remembering
  • slice() with no arguments makes a shallow copy of the whole array.
  • splice(index) with no count removes everything from index to the end. Pass a count, like splice(index, 1), when you mean one item.
  • const stops you from putting a different array in the variable. It does not stop splice or fill from changing the array.
  • Removing the item at index 0 makes every other item move down one place. On a very large list, doing this many times can be slow, so measure it before you rely on it.
  • join makes plain text, not safe HTML. Show text a person typed with textContent, not by building an HTML string.
  • toSpliced does the job of splice without changing the original. Check that the browsers you support have it. The sorting lesson compares it with splice.

Common misconceptions

"slice and splice do the same thing."

They don't. slice copies items and leaves the array alone. splice changes the array and gives back the removed items.

"A copied array shares nothing with the original."

The copies in this lesson are shallow. If an item is an object or an inner array, the copy and the original share it.

"join writes null and undefined as words."

join turns null and undefined into empty text. So two separators can end up side by side.

"split always drops empty pieces."

It keeps them. "a,b,,c".split(",") includes an empty string, "".

"fill() makes a separate object for each slot."

It puts the same one object in every slot. Use Array.from with a function that makes a new object each time.

"copyWithin gives back a safe copy."

It changes the array and gives back that same array. "Copy" here means copying items inside the same array.

Does it change the original array?
  • items.slice(1, 3)
  • items.splice(1, 2, "x")
  • a.concat(b)
  • [...a, ...b]
  • items.join('-')
  • items.fill(0)
  • items.copyWithin(0, 2)
  • Array.from('hey')
Try it yourself
0 of 8 correct

Put each line in a group. Read the explanation even when you get it right; it covers the tricky cases.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Practice: copy, cut, join, and build

5 EXERCISES
Exercise 1 · Warm-upPredict slice, splice, and the original

Predict all three logs. Type the first log in the answer box, then check the solution for all three.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const letters = ["a", "b", "c", "d"];
const copied = letters.slice(1, 3);
const removed = letters.splice(2, 1, "X");
console.log(copied.join(""));
console.log(removed.join(""));
console.log(letters.join(""));

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeRemove an item without changing the original

    Remove green at index 1 without using splice. What does the new array print?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const items = ["red", "green", "blue", "gold"];
    const index = 1;
    const withoutGreen = [...items.slice(0, index), ...items.slice(index + 1)];
    console.log(withoutGreen.join(","));
    console.log(items.join(","));

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeSplit words and join them back

      Turn "a b c" into ["a", "b", "c"], then back into one string with | between the letters.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const words = "a b c".split(" ");
      console.log(words.join("|"));

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeBuild even numbers with Array.from

        Build [0, 2, 4, 6] without typing the four numbers yourself.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const evens = Array.from({ length: 4 }, (_, i) => i * 2);
        console.log(evens.join(","));

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeFix the shared-object fill bug

          Change the first line so that changing the first row does not change the second row.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const rows = new Array(3).fill({ done: false });
          rows[0].done = true;
          console.log(rows[1].done);

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            8 QUESTIONS

            For each question, follow two things one at a time: what the method gives back, and what the original array holds after. Your first answer is the one that counts, and every choice explains why it is right or wrong.

            Lesson quiz · 8 questionsScore: first tries count
            1. Question 1 of 8Which sentence describes slice and splice?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does slice(-2) give back, and what is left in letters?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const letters = ["a", "b", "c"];
              console.log(letters.slice(-2).join(""));
              console.log(letters.join(""));

              Choose an answer to see the explanation.

            3. Question 3 of 8What does splice give back here, and what is left in nums?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const nums = [1, 2, 3, 4];
              console.log(nums.splice(1, 2, 9).join(","));
              console.log(nums.join(","));

              Choose an answer to see the explanation.

            4. Question 4 of 8What does join print when the array holds null and undefined?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log([null, undefined, 1].join("-"));

              Choose an answer to see the explanation.

            5. Question 5 of 8What does split print with no limit, and then with a limit of 2?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log("a,b,,c".split(",").join("|"));
              console.log("a,b,,c".split(",", 2).join("|"));

              Choose an answer to see the explanation.

            6. Question 6 of 8Which code makes [3], an array with one item, the number 3?

              Choose an answer to see the explanation.

            7. Question 7 of 8After fill with an object, what does rows[1].done print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const rows = new Array(2).fill({ done: false });
              rows[0].done = true;
              console.log(rows[1].done);

              Choose an answer to see the explanation.

            8. Question 8 of 8What does copyWithin give back, and what is left in values?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const values = [1, 2, 3, 4, 5];
              console.log(values.copyWithin(0, 3).join(","));
              console.log(values.join(","));

              Choose an answer to see the explanation.

            Key takeaways

            • slice makes a shallow copy of part of an array. splice changes the array and gives back the removed items.
            • Spread and concat make a new outer array, but objects inside it are still shared.
            • join gives back a string. split gives back an array of strings, and it keeps empty pieces.
            • Array.from builds an array from an iterable or an array-like object. Array.of(3) means [3].
            • fill and copyWithin change the array. Avoid fill() unless you want every slot to share one object.

            Remember the one-line summary.
            Copy with slice, spread, concat, and Array.from. Change the array with splice, fill, and copyWithin. Turn arrays into text and back with join and split.

            Up next: Searching arrays.

            CompleteFrontend Clear concepts. Working examples.