JavaScript Basics: Clean, Search, and Split Strings
Text often needs a little preparation before a program can use it. This tutorial covers trimming whitespace, finding text, splitting fields, and replacing repeated text. It also shows why an emoji can have a surprising length.
All examples use built-in features and were tested on Linux with Node.js v24.19.0. Assertions stop the program if a result differs from the expected value. A successful run prints the output shown below.
Prepare a scratch directory
Run these commands in Bash, then keep using the same terminal for this tutorial:
You need Bash, a text editor, the mktemp, rm, and rmdir utilities, and Node.js on your PATH. Save source files as UTF-8; their .mjs extension selects ES modules.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Create each named file in this directory with your editor. No package installation is needed.
1. Clean and search a label
Save this as clean-label.mjs:
import assert from 'node:assert/strict';
const original = ' Learn JavaScript \n';
const label = original.trim();
assert.equal(label, 'Learn JavaScript');
assert.equal(original, ' Learn JavaScript \n');
assert.equal(label.includes('JavaScript'), true);
assert.equal(label.includes('javascript'), false);
assert.equal(label.includes(''), true);
assert.equal(' \t\n'.trim(), '');
console.log(label);
console.log(`Exact match: ${label.includes('JavaScript')}`);
console.log(`Lowercase match: ${label.includes('javascript')}`);Run it:
node clean-label.mjsOutput:
Learn JavaScript
Exact match: true
Lowercase match: falsetrim() removes whitespace from both ends. It leaves internal spaces alone and returns a new string. The original value stays unchanged.
includes() is case-sensitive. An empty search string always matches, so check for an empty query separately if your application should reject it.
2. Split simple fields and replace text
Save this as split-fields.mjs:
import assert from 'node:assert/strict';
const line = 'red|green||blue|';
const fields = line.split('|');
assert.deepEqual(fields, ['red', 'green', '', 'blue', '']);
assert.deepEqual(''.split('|'), ['']);
const original = 'read-me read-me';
const readable = original.replaceAll('-', ' ');
assert.equal(readable, 'read me read me');
assert.equal(original, 'read-me read-me');
// A function returns replacement text literally, including dollar signs.
const literal = 'TOKEN TOKEN'.replaceAll('TOKEN', () => '$&');
assert.equal(literal, '$& $&');
console.log(`Fields: ${fields.length}`);
console.log(`Empty fields preserved: ${fields[2] === '' && fields[4] === ''}`);
console.log(readable);
console.log(literal);Run it:
node split-fields.mjsOutput:
Fields: 5
Empty fields preserved: true
read me read me
$& $&split() returns fields separated by the supplied delimiter. Adjacent or trailing delimiters produce empty fields. Decide whether those empty fields matter before removing them. This simple format has no quoting or escaping rules; splitting on a comma is not a general CSV parser.
replaceAll() replaces every match and returns a new string. A string search pattern is literal, so '.' searches for a dot. Replacement strings have special sequences such as $&, which inserts the matched text. Use a replacement function, as above, when the replacement must be taken literally. If you use a regular expression as the search pattern, it must have the g flag.
3. Understand what string length counts
Save this as string-length.mjs:
import assert from 'node:assert/strict';
const emoji = '😀';
assert.equal(emoji.length, 2);
assert.equal(emoji.split('').length, 2);
assert.equal([...emoji].length, 1);
// One displayed accented letter, written as two Unicode code points.
const accented = 'e\u0301';
assert.equal([...accented].length, 2);
console.log(`Emoji UTF-16 units: ${emoji.length}`);
console.log(`Emoji code points: ${[...emoji].length}`);
console.log(`Accented-letter code points: ${[...accented].length}`);Run it:
node string-length.mjsOutput:
Emoji UTF-16 units: 2
Emoji code points: 1
Accented-letter code points: 2JavaScript strings use UTF-16 code units. length counts those units, and split('') separates them. Some code points, including this emoji, occupy two units. String iteration, used by [...text], works by code point instead. Even code points do not always correspond to displayed characters: a letter plus a combining accent can be displayed together. Avoid treating either count as a universal user-visible character count.
Clean up
In the same terminal, remove only the files created here, return to your original directory, and remove the now-empty scratch directory:
rm -- clean-label.mjs split-fields.mjs string-length.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirAcknowledgements
This post was created with assistance from AI.