[ { "method": "charAt / s[i]", "tier": "core", "task": "Get the character at index i", "call": "s[i] // or s.charAt(i)", "mutates": false, "returns": "1-char string; s[i] gives undefined out of range, charAt gives ''", "example": "return ['abc'[1],'abc'.charAt(5),'abc'[5]];", "expected": "[\"b\",\"\",null]", "gotcha": "Strings are immutable: s[0] = 'x' silently does nothing." }, { "method": "charCodeAt", "tier": "core", "task": "Get the char code of the character at index i", "call": "s.charCodeAt(i)", "mutates": false, "returns": "number (UTF-16 code unit)", "example": "return ['a'.charCodeAt(0),'c'.charCodeAt(0)-'a'.charCodeAt(0)];", "expected": "[97,2]", "gotcha": "Alphabet index idiom: s.charCodeAt(i) - 97." }, { "method": "String.fromCharCode", "tier": "core", "task": "Turn a char code into a character", "call": "String.fromCharCode(code)", "mutates": false, "returns": "string", "example": "return String.fromCharCode(97+2);", "expected": "\"c\"", "gotcha": "Static method on String, not on a string value." }, { "method": "split", "tier": "core", "task": "Split a string into an array by a separator", "call": "s.split(sep)", "mutates": false, "returns": "array of strings", "signature": "s.split(separator, limit) // split('') = chars", "example": "return ['a,b'.split(','),'abc'.split('')];", "expected": "[[\"a\",\"b\"],[\"a\",\"b\",\"c\"]]" }, { "method": "[...s]", "tier": "core", "task": "Turn a string into an array of characters", "call": "[...s] // or Array.from(s)", "mutates": false, "returns": "new array of characters", "example": "return [...'abc'];", "expected": "[\"a\",\"b\",\"c\"]", "gotcha": "Unlike split(''), spread keeps emoji/surrogate pairs whole." }, { "method": "reverse a string", "tier": "core", "task": "Reverse a string", "call": "[...s].reverse().join('')", "mutates": false, "returns": "new string", "example": "return [...'abc'].reverse().join('');", "expected": "\"cba\"", "gotcha": "Strings have no reverse(); go via an array." }, { "method": "slice", "tier": "core", "task": "Get s[i..j) as a substring", "call": "s.slice(i, j)", "mutates": false, "returns": "new string; end exclusive", "signature": "s.slice(start, end) // end exclusive, negatives count from the end", "example": "return ['abcdef'.slice(1,3),'abcdef'.slice(-2)];", "expected": "[\"bc\",\"ef\"]" }, { "method": "substring", "tier": "core", "task": "Substring by two indices (and how it differs from slice)", "call": "s.substring(i, j)", "mutates": false, "returns": "new string; end exclusive", "signature": "s.substring(start, end) // swaps args if start > end, negatives → 0", "example": "return ['abcdef'.substring(3,1),'abcdef'.slice(3,1),'abcdef'.substring(-2)];", "expected": "[\"bc\",\"\",\"abcdef\"]", "gotcha": "Prefer slice(): substring swaps arguments and treats negatives as 0." }, { "method": "indexOf", "tier": "core", "task": "Find the index of a substring (-1 if absent)", "call": "s.indexOf(sub)", "mutates": false, "returns": "first index, or -1", "signature": "s.indexOf(searchString, fromIndex)", "example": "return ['hello'.indexOf('l'),'hello'.indexOf('z')];", "expected": "[2,-1]" }, { "method": "includes", "tier": "core", "task": "Check whether a string contains a substring", "call": "s.includes(sub)", "mutates": false, "returns": "boolean", "example": "return 'hello'.includes('ell');", "expected": "true", "gotcha": "Case-sensitive; a RegExp argument throws." }, { "method": "startsWith", "tier": "core", "task": "Check whether a string starts with a prefix", "call": "s.startsWith(prefix)", "mutates": false, "returns": "boolean", "example": "return 'hello'.startsWith('he');", "expected": "true" }, { "method": "endsWith", "tier": "core", "task": "Check whether a string ends with a suffix", "call": "s.endsWith(suffix)", "mutates": false, "returns": "boolean", "example": "return 'hello'.endsWith('lo');", "expected": "true" }, { "method": "toLowerCase", "tier": "core", "task": "Lowercase a string", "call": "s.toLowerCase()", "mutates": false, "returns": "new string", "example": "return 'aBc'.toLowerCase();", "expected": "\"abc\"" }, { "method": "toUpperCase", "tier": "core", "task": "Uppercase a string", "call": "s.toUpperCase()", "mutates": false, "returns": "new string", "example": "return 'aBc'.toUpperCase();", "expected": "\"ABC\"" }, { "method": "trim", "tier": "core", "task": "Strip whitespace from both ends", "call": "s.trim()", "mutates": false, "returns": "new string", "example": "return ' a b '.trim();", "expected": "\"a b\"" }, { "method": "repeat", "tier": "core", "task": "Repeat a string n times", "call": "s.repeat(n)", "mutates": false, "returns": "new string", "example": "return 'ab'.repeat(3);", "expected": "\"ababab\"", "gotcha": "Negative n throws RangeError." }, { "method": "padStart", "tier": "core", "task": "Left-pad a string to a length (e.g. zero-pad)", "call": "s.padStart(len, '0')", "mutates": false, "returns": "new string", "signature": "s.padStart(targetLength, padString)", "example": "return '5'.padStart(3,'0');", "expected": "\"005\"" }, { "method": "padEnd", "tier": "core", "task": "Right-pad a string to a length", "call": "s.padEnd(len, ' ')", "mutates": false, "returns": "new string", "signature": "s.padEnd(targetLength, padString)", "example": "return 'ab'.padEnd(5,'.');", "expected": "\"ab...\"" }, { "method": "replace", "tier": "core", "task": "Replace occurrences of a pattern (first only vs all)", "call": "s.replace(pattern, replacement)", "mutates": false, "returns": "new string", "signature": "s.replace(patternOrString, replacementOrFn)", "example": "return ['aaa'.replace('a','b'),'aaa'.replace(/a/g,'b')];", "expected": "[\"baa\",\"bbb\"]", "gotcha": "A string pattern replaces only the FIRST match. Use /x/g or replaceAll." }, { "method": "replaceAll", "tier": "core", "task": "Replace ALL occurrences of a substring", "call": "s.replaceAll(sub, replacement)", "mutates": false, "returns": "new string", "signature": "s.replaceAll(patternOrString, replacementOrFn)", "example": "return 'aaa'.replaceAll('a','b');", "expected": "\"bbb\"", "gotcha": "A RegExp argument must have the g flag or it throws." }, { "method": "at", "tier": "core", "task": "Get the LAST character (or nth from the end)", "call": "s.at(-1)", "mutates": false, "returns": "1-char string, or undefined", "example": "return ['abc'.at(-1),'abc'.at(0)];", "expected": "[\"c\",\"a\"]" }, { "method": "match", "tier": "core", "task": "Find all regex matches in a string", "call": "s.match(/\\d+/g)", "mutates": false, "returns": "array of matches, or null if none", "example": "return ['a1b22'.match(/\\d+/g),'abc'.match(/\\d+/g)];", "expected": "[[\"1\",\"22\"],null]", "gotcha": "Without the g flag you get a single match object, not all matches. null → use ?? []." }, { "method": "matchAll", "tier": "core", "task": "Iterate all regex matches including capture groups", "call": "[...s.matchAll(/(\\d)(\\w)/g)]", "mutates": false, "returns": "iterator of match arrays", "example": "return [...'1a2b'.matchAll(/(\\d)(\\w)/g)].map((m)=>m[1]+m[2]);", "expected": "[\"1a\",\"2b\"]", "gotcha": "The regex must have the g flag or it throws." }, { "method": "trimStart", "tier": "rare", "task": "Strip whitespace from the START only", "call": "s.trimStart()", "mutates": false, "returns": "new string", "example": "return ' a '.trimStart();", "expected": "\"a \"" }, { "method": "trimEnd", "tier": "rare", "task": "Strip whitespace from the END only", "call": "s.trimEnd()", "mutates": false, "returns": "new string", "example": "return ' a '.trimEnd();", "expected": "\" a\"" }, { "method": "lastIndexOf", "tier": "rare", "task": "Find the LAST index of a substring", "call": "s.lastIndexOf(sub)", "mutates": false, "returns": "last index, or -1", "example": "return 'hello'.lastIndexOf('l');", "expected": "3" }, { "method": "substr", "tier": "rare", "task": "Substring by start index and LENGTH (deprecated)", "call": "s.substr(start, length)", "mutates": false, "returns": "new string", "signature": "s.substr(start, length) // deprecated; use slice", "example": "return 'abcdef'.substr(1,3);", "expected": "\"bcd\"", "gotcha": "Second arg is a length, not an end index. Deprecated." }, { "method": "concat", "tier": "rare", "task": "Concatenate strings with a method call", "call": "s.concat(a, b)", "mutates": false, "returns": "new string", "example": "return 'a'.concat('b','c');", "expected": "\"abc\"", "gotcha": "Just use + or a template literal." }, { "method": "search", "tier": "rare", "task": "Find the index of a regex match", "call": "s.search(/c/)", "mutates": false, "returns": "index, or -1", "example": "return 'abc'.search(/c/);", "expected": "2" }, { "method": "localeCompare", "tier": "rare", "task": "Compare two strings for sorting", "call": "a.localeCompare(b)", "mutates": false, "returns": "negative / 0 / positive number", "example": "return ['b','a','c'].sort((x,y)=>x.localeCompare(y));", "expected": "[\"a\",\"b\",\"c\"]", "gotcha": "Locale-aware and slower; for plain code-unit order use a < b ? -1 : 1." }, { "method": "codePointAt", "tier": "rare", "task": "Get the full Unicode code point at index i", "call": "s.codePointAt(i)", "mutates": false, "returns": "number", "example": "return '😀'.codePointAt(0);", "expected": "128512", "gotcha": "charCodeAt would return only half of the surrogate pair." }, { "method": "normalize", "tier": "rare", "task": "Normalize Unicode (e.g. strip accents with NFD)", "call": "s.normalize('NFD')", "mutates": false, "returns": "new string", "example": "return 'é'.normalize('NFD').length;", "expected": "2" } ]