JavaScript type

The latest ECMAScript standard defines 1 object data type and 7 primitive data types.

The 7 primitive data types are:

  1. Boolean. true and false.
  2. null. A special keyword denoting a null value. (Because JavaScript is case-sensitive, null is not the same as Null, NULL, or any other variant.)
  3. undefined. A top-level property whose value is not defined.
  4. Number. An integer or floating point number. For example: 42 or 3.14159.
  5. BigInt. An integer with arbitrary precision. For example: 9007199254740992n.
  6. String. A sequence of characters that represent a text value. For example: “Howdy”
  7. Symbol (new in ECMAScript 2015). A data type whose instances are unique and immutable.

ECMAScript has two built-in numeric types: Number and BigInt.

Note:

All primitives (the values themselves not the variables) are immutable. A variable can be reassigned a primitive value, but the existing primitive value can not be changed like an object.

validate

https://dmitripavlutin.com/javascript-defined-variable-checking/

// Examples of defined variables:

const pi = 3.14; // pi is defined
let result;      // result is defined

window.message = 'Hello';
message;         // message is defined

Find whether a variable is defined or not.

The typeof operator determines the variable’s type. typeof myVar can evaluate to one of the values: 'boolean', 'number', 'string', 'symbol', 'object', 'function' and 'undefined'.

// missingVar is not defined

typeof missingVar; // Doesn't throw ReferenceError

missingVar;        // Throws ReferenceError

942

https://stackoverflow.com/questions/5113374/javascript-check-if-variable-exists-is-defined-initialized

The typeof operator will check if the variable is really undefined.

if (typeof variable === 'undefined') {
    // variable is undefined
}

The typeof operator, unlike the other operators, doesn’t throw a ReferenceError exception when used with an undeclared variable.

However, do note that typeof null will return "object". We have to be careful to avoid the mistake of initializing a variable to null. To be safe, this is what we could use instead:

if (typeof variable === 'undefined' || variable === null) {
    // variable is undefined or null
}

Boolean

A Boolean is a logical data type that can have only the values true or false.

Truthy value and Falsy value:

  • JavaScript uses type conversion to coerce any value to a Boolean in Boolean contexts (like conditionals and loops).
  • All values are truthy unless they are defined as falsy which are listed below.

All the values considered to be false

All the values that considered to be false when encountered in a Boolean context like if condition (See Falsy value):

  • false The keyword false.
  • 0 The Number zero (so, also 0.0, etc., and 0x0).
  • -0 The Number negative zero (so, also -0.0, etc., and -0x0).
  • 0n The BigInt zero (so, also 0x0n). Note that there is no BigInt negative zero — the negation of 0n is 0n.
  • "", '' , “` ` Empty string value.
  • null null
  • undefined undefined
  • NaN NaN
  • document.all Objects are falsy if and only if they have the [[IsHTMLDDA]] internal slot.That slot only exists in document.all and cannot be set using JavaScript.

The logical AND && operator

Note the logical AND (&&) returns the value of the first falsy operand encountered when evaluating from left to right, or the value of the last operand if they are all truthy.

Examples

console.log(1 && 0 && 'abc')     // 0
console.log(false && 1)          // false
console.log(true && 'abc')       // 'abc'

Convert a Boolean to an Boolean object

The Boolean object is an object wrapper for a boolean value.

Examples

var x = new Boolean(false);
if (x) { // x is an object not a boolean primitive 
  // this code is executed
}

x = false
if (x) {
  // this code is not executed
}

// Do not use a Boolean object to convert a non-boolean value to a boolean value. 
x = Boolean(expression);     // use this...
x = !!(expression);          // ...or this
x = new Boolean(expression); // don't use this!

Boolean object:

The value passed as the first parameter is converted to a boolean value, if necessary. If the value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object, an empty array ([]), or the string “false“, create an object with an initial value of true.

Number

Number type:

The Number type is a double-precision 64-bit binary format IEEE 754 value (numbers between -(2^53 − 1) and 2^53 − 1). In addition to representing floating-point numbers, the number type has three symbolic values: +Infinity, -Infinity, and NaN (“Not a Number”).

To check for the largest available value or smallest available value within ±Infinity, you can use the constants Number.MAX_VALUE or Number.MIN_VALUE.

Examples

// 0 is represented as both -0 and +0. (0 is an alias for +0.)
console.log(+0 === -0);    // true

+Infinity, -Infinity, and NaN

// Infinity and -Infinity
console.log(42 / +0); // Infinity
console.log(42 / -0); // -Infinity

// NaN
console.log(NaN); // NaN

// Use isNaN() to determineswhether a value is NaN or not.
console.log(isNaN('100F'));      // true
console.log(isNaN(1.23));        // false
console.log(isNaN('3.14'));      // false
console.log(isNaN('0.0314E+2')); // false

Starting with ECMAScript 2015, you are also able to check if a number is in the double-precision floating-point number range.

// Check if a number is in the double-precision floating-point number range.

// Out of safe range, the precision may be lost.
console.log(Number.isSafeInteger(Math.pow(2, 53))); // false
// In safe range, the precision is safe.
console.log(Number.isSafeInteger(Math.pow(2, 53) - 1)); // true
// The max safe inteer and the min safe integer.
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

Resource

JavaScript Map

This article illustrates the operations of JavaScript Map. Most of the content come from MDN.

About Map

The Map object holds key-value pairs and remembers the original insertion order of the keys. It iterates its elements in insertion order — a for...of loop returns an array of [key, value] for each iteration.

  • Key equality

    NaN is considered the same as NaN (even though NaN !== NaN) and all other values are considered equal according to the semantics of the === operator.

    let myMap = new Map()
    myMap.set(NaN, 'not a number')
    
    myMap.get(NaN)
    // "not a number"
    
    let otherNaN = Number('foo')
    myMap.get(otherNaN)
    // "not a number"
    

Basic operations

Create

Use the Map() constructor creates Map objects.

Syntax:

new Map([iterable]);
// iterable can be an Array or other iterable objects whose elements are key-value pairs.

Examples:

let map1 = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let map2 = new Map();
map2.set(1, 'one');
map2.set(2, 'two');
map2.set(3, 'three');

Size

console.log(map1.size);

Loop

There are several ways to loop a Map object.

iterator or entries

The initial value of the @@iterator property is the same function object as the initial value of the entries method. The map iterator function, which is the entries() function by default.

iterator:

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

const iterator1 = map1[Symbol.iterator]();

for (const item of iterator1) {
    console.log(item);
}
// expected output: Array ["0", "foo"]
// expected output: Array [1, "bar"]

entries():

The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object in insertion order. In this particular case, this iterator object is also an iterable, so the for-of loop can be used.

const iterator1 = map1.entries();
for (const item of iterator1) {
    console.log(item);
}
// expected output: Array ["0", "foo"]
// expected output: Array [1, "bar"]

for…of

let myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');

// -------- Loop key, value pairs
for (let [key, value] of myMap) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

// -------- Loop keys
for (let key of myMap.keys()) {
  console.log(key)
}
// 0
// 1

// -------- Loop values
for (let value of myMap.values()) {
  console.log(value)
}
// zero
// one

// -------- entries
for (let [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

forEach

The forEach() method executes a provided function once per each key/value pair in the Map object, in insertion order.

function logMapElements(value, key, map) {
  console.log(`m[${key}] = ${value}`);
}

new Map([['foo', 3], ['bar', {}], ['baz', undefined]])
  .forEach(logMapElements);

// expected output: "m[foo] = 3"
// expected output: "m[bar] = [object Object]"
// expected output: "m[baz] = undefined"

Syntax

myMap.forEach(callback([value][, key][, map])[, thisArg])

Parameters

  • callback

    Function to execute for each entry of myMap. It takes the following arguments:

    • value Optional. Value of each iteration.
    • key Optional. Key of each iteration.
    • map Optional. The map being iterated (myMap in the above Syntax box).
  • thisArg Optional

    Value to use as this when executing callback.

Delete

  • delete(), deletes the specified element.
  • clear(), deletes all elements.

delete()

The delete(key) method removes the specified element from a Map object by key.

It returns true if an element in the Map object existed and has been removed, or false if the element does not exist.

const map1 = new Map();
map1.set('bar', 'foo');

console.log(map1.delete('bar'));
// expected result: true
// (true indicates successful removal)

console.log(map1.has('bar')); // false

clear()

The clear() method removes all elements from a Map object.

const map1 = new Map();

map1.set('bar', 'baz');
map1.set(1, 'foo');
console.log(map1.size); // 2

map1.clear();
console.log(map1.size); // 0

get()

The get(key) method returns a specified element from a Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map object.

const map1 = new Map();
map1.set('bar', 'foo');

console.log(map1.get('bar')); // "foo"
console.log(map1.get('baz')); // undefined

has()

The has(key) method returns a boolean indicating whether an element with the specified key exists or not.

const map1 = new Map();
map1.set('bar', 'foo');

console.log(map1.has('bar')); // true
console.log(map1.has('baz')); // false

set()

The set(key, value) method adds or updates an element with a specified key and a value to a Map object.

const map1 = new Map();

map1.set('bar', 'foo');
console.log(map1.get('bar')); // "foo"

map1.set('bar', 'foo2');
console.log(map1.get('bar')); // "foo2"

This is the only right way to update or add an element through set().

Note

It is possible to set properties of a Map like other generic objects, but this will cause considerable confusion. For these properties set in this way are not stored in the Map for queries. Other operations on the data fail:

let wrongMap = new Map()
wrongMap['bla'] = 'blaa'
wrongMap['bla2'] = 'blaaa2'

console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }

// Other operations on the data fail.

wrongMap.has('bla')    // false
wrongMap.delete('bla') // false
console.log(wrongMap)  // Map { bla: 'blaa', bla2: 'blaaa2' }

Members

entities()

The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object in insertion order. In this particular case, this iterator object is also an iterable, so the for-of loop can be used. When the protocol [Symbol.iterator] is used, it returns a function that, when invoked, returns this iterator itself.

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

const iterator1 = map1.entries();

console.log(iterator1.next().value);
// expected output: ["0", "foo"]

console.log(iterator1.next().value);
// expected output: [1, "bar"]

keys()

The keys() method returns a new Iterator object that contains the keys for each element in the Map object in insertion order.

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

const iterator1 = map1.keys();

console.log(iterator1.next().value);
// expected output: "0"

console.log(iterator1.next().value);
// expected output: 1

values()

The values() method returns a new Iterator object that contains the values for each element in the Map object in insertion order.

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

const iterator1 = map1.values();

console.log(iterator1.next().value);
// expected output: "foo"

console.log(iterator1.next().value);
// expected output: "bar"

Other operations

Map and Array

Array to Map

It is easy to convert an Array to a Map, for Map() constructor accepts an array as its parameter:

let kvArray = [['key1', 'value1'], ['key2', 'value2']];

// Use the regular Map constructor to transform a 2D key-value Array into a map
let myMap = new Map(kvArray);

Map to Array

To convert a Map to an Array:

let kvArray = [['key1', 'value1'], ['key2', 'value2']];
let myMap = new Map(kvArray);

// Use Array.from() to transform a map into a 2D key-value Array
let arr1 = Array.from(myMap);
console.log(arr1); // Will show you exactly the same Array as kvArray

// A succinct way to do the same, using the spread syntax
let arr2 = [...myMap];
console.log(arr2);

let arr3 = Array.from(myMap.keys());
console.log(arr3); // ["key1", "key2"]

Map and JSON

There is not direct support to convert a map to JSON, we can do that by using array.

Map to Json

let jsonStr = JSON.stringify([...myMap]);
// Or
let jsonStr2 = JSON.stringify(Array.from(myMap));

JSON to Map

let myMap = Map(JSON.parse(jsonStr));

Object vs Map

An object is similar to a map, both of them have a key-value structure. Objects vs Maps lists the differences between objects and a maps. Below are some main of them :

  • Key type:
    • The keys of an Object must be either a String or a Symbol.
    • A Map‘s keys can be any value (including functions, objects, or any primitive).
  • Size:
    • You need to get the item count of an object manually.
    • Use size property to directly get size of a map.
  • Iteration
    • By default, Object does not implement an iteration protocol, it is not directly iterable using for...of statement (by default). The for…in statement allows you to iterate over the enumerable properties of an object.
    • A Map is iterable, it can be directly iterated.
  • Performance

    When it comes to scenarios involving frequent additions and removal:

    • A map performs better.

Suggestions about object vs map

geeksforgeeks: Map vs Object:

Object is much more than a Map, it shouldn’t be used just for the purpose of hashing if there exists another choice.

Reference

JavaScript String

This article lists the operations of JavaScript String and the things you want to know about it. Treat it as a reference list.

About String in JavaScript

As in other programming languages, a string in JavaScript is also a sequence of characters.

A Sting is one of the seven primitive data types in JavaScript and String object is a wrapper for a String primitive.

A set of 16-bit unsigned integer values

It is a set of “elements” of 16-bit unsigned integer values.

Immutable

Unlike some programming languages (such as C), JavaScript strings are immutable. This means that once a string is created, it is not possible to modify it.

String primitives and String objects

JavaScript automatically converts primitives to String objects, so that it’s possible to use String object methods for primitive strings. In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup.

let s_prim = 'foo'
let s_obj = new String(s_prim)

console.log(typeof s_prim) // Logs "string"
console.log(typeof s_obj)  // Logs "object"

String primitives and String objects also give different results when using eval(). Primitives passed to eval are treated as source code; String objects are treated as all other objects are, by returning the object. For example:

let s1 = '2 + 2'              // creates a string primitive
let s2 = new String('2 + 2')  // creates a String object
console.log(eval(s1))         // returns the number 4
console.log(eval(s2))         // returns the string "2 + 2"

A String object can always be converted to its primitive counterpart with the valueOf() method.

console.log(eval(s2.valueOf()))  // returns the number 4

Escape notation

Code Output
U+0000 NULL character
' single quote
" double quote
\ backslash
n new line
r carriage return
v vertical tab
t tab
b backspace
f form feed
uXXXX (where XXXX is 4 hex digits; range of 0x00000xFFFF) UTF-16 code unit / Unicode code point between U+0000 and U+FFFF
u{X}u{XXXXXX} (where X…XXXXXX is 1–6 hex digits; range of 0x00x10FFFF) UTF-32 code unit / Unicode code point between U+0000 and U+10FFFF
xXX (where XX is 2 hex digits; range of 0x000xFF) ISO-8859-1 character / Unicode code point between U+0000 and U+00FF

Basic operations

Create strings

Strings can be created as primitives from string literals, or as object using String() constructor. In most situations, they can be used interchangeably.

const str1 = 'Hello';
const str2 = "World";
const str3 = `A template string`;
const str4 = new String('A string object');

A string literal can be enclosed by single quotes '' or double quotes"", both of them are treated identically. Or you can use a pair of backticks ““ to create a template string (or a template literal).

Template literals (Template strings)

Template literals can be useful, below are 2 of the examples:

They can contain placeholders:

let a = 5;
let b = 10;
console.log(`a is ${a}, b is ${b}`); // a is 5, b is 10

console.log(`a * 10 times: ${a.repeat(10)}`); // a * 10 times: aaaaaaaaaa

They can be used to represent multiple lines in a direct way:

console.log(`string text line 1
string text line 2`);

Multiple line of strings

There are several ways to represent multiple line of string or long strings in JavaScript.

1.Use + to append multiple strings together:

let longString = "This is a very long string which needs " +
                 "to wrap across multiple lines because " +
                 "otherwise my code is unreadable.";

2.Use the backslash character (“) at the end of each line to indicate that the string will continue on the next line:

let longString = "This is a very long string which needs 
to wrap across multiple lines because 
otherwise my code is unreadable.";

3.Use a template string:

let longString = `This is a very long string which needs
 to wrap across multiple lines because
 otherwise my code is unreadable.`;

Length

const str1 = 'Hello';
console.log(str1.length); // 5

Access characters or elements

To access an individual character:

return 'cat'.charAt(1); // returns "a"
// Or
return 'cat'[1] // returns "a"

Not it will not succeed to delete or assign a new value via [].

Check

startsWith()

The startsWith(searchString[, position] method determines whether a string begins with the characters of a specified string, returning true or false as appropriate.

  • position, the position in this string at which to begin searching for searchString. Defaults to 0.
const str1 = 'Hello!';

console.log(str1.startsWith('He'));    // true
console.log(str1.startsWith('lo', 3)); // true

console.log(str1.startsWith('A'));     // false

endsWith()

The endsWith(searchString[, length]) method determines whether a string ends with the characters of a specified string, returning true or false as appropriate.

  • length, it is used as the length of str. Defaults to str.length.
const str1 = 'Hello!';

console.log(str1.endsWith('llo'));    // true
console.log(str1.endsWith('llo', 3)); // false

console.log(str1.endsWith('?'));      // false

Compare

Use operators to compare two strings.

const a = 'a'
const b = 'b'

console.log( a < b);  // true
console.log( a <= b); // true
console.log( a > b);  // false

Equal check:

  • == return true if the operands are equal.
  • === returns true if the operands are equal and of the same type.
const a = 'Hello';
const b = new String('Hello');
const c = 'hello';

const d = 1;
const f = '1';

//------------- equal: ==

// Compare the strings in a and b for being equal in the usual case-sensitive way.
console.log(a == b); // true
console.log(a == c); // false
console.log(d == f); // true

// Case-insentitive
console.log(c.toUpperCase() == c.toUpperCase()); // true

// ------------ strict equal: ===

console.log(a === b); // false

Concat

contact()

The concat() method concatenates the string arguments to the calling string and returns a new string.

Examples

// To concatenate two or more strings.

const str1 = 'Hello';
const str2 = 'World';

console.log(str1.concat(' ', str2));
// expected output: "Hello World"

console.log(str1.concat(' ', str2, ', ', str1, ' ', str2));
// expected output: "Hello World, Hello World"

Index of

indexOf()

indexOf(searchValue[, fromIndex]) returns the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. Returns -1 if the value is not found.

lastIndexOf()

The lastIndexOf(searchValue[, fromIndex]) method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from fromIndex. Returns -1 if the value is not found.

Lower, upper

toLowerCase()

The toLowerCase() method returns the calling string value converted to lower case.

const sentence = 'The quick brown fox jumps over the lazy dog.';

console.log(sentence.toLowerCase());
// expected output: "the quick brown fox jumps over the lazy dog."

toUpperCase()

The toUpperCase() method returns the calling string value converted to uppercase (the value will be converted to a string if it isn’t one).

const sentence = 'The quick brown fox jumps over the lazy dog.';

console.log(sentence.toUpperCase());
// expected output: "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG."

Pad

padEnd()

The padEnd(targetLength [, padString) method pads the current string with a given string (repeated, if needed) so that the resulting string reaches a given length. The padding is applied from the end of the current string.

  • padString, if it is too long to stay within targetLength, it will be truncated. Default value is " ".
const str1 = 'Breaded Mushrooms';

console.log(str1.padEnd(25, '.'));
// expected output: "Breaded Mushrooms........"

const str2 = '200';

console.log(str2.padEnd(5));
// expected output: "200  "

padStart()

The padStart(targetLength [, padString]) method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start of the current string.

const str1 = '5';

console.log(str1.padStart(2, '0'));
// expected output: "05"

const fullNumber = '2034399002125581';
const last4Digits = fullNumber.slice(-4);
const maskedNumber = last4Digits.padStart(fullNumber.length, '*');

console.log(maskedNumber);
// expected output: "************5581"

Repeat

repeat()

To make a string repeat multiple times:

const a = 'a';

console.log(chorus.repeat(10));
// expected output: "aaaaaaaaaa"

Replace

The replace() and replaceAll return a new string with some or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match.

For replace(), if pattern is a string, only the first occurrence will be replaced.

replace()

The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.

Syntax

replace(regexp|substr, newSubstr|function)

Examples

const p = 'The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?';

console.log(p.replace('dog', 'monkey'));
// expected output: "The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?"


const regex = /Dog/i;
console.log(p.replace(regex, 'ferret'));
// expected output: "The quick brown fox jumps over the lazy ferret. If the dog reacted, was it really lazy?"

replaceAll()

The replaceAll() method returns a new string with all matches of a pattern replaced by a replacement.

Syntax

replaceAll(regexp|substr, newSubstr|function)

Examples

const p = 'The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?';

console.log(p.replaceAll('dog', 'monkey'));
// expected output: "The quick brown fox jumps over the lazy monkey. If the monkey reacted, was it really lazy?"


// global flag required when calling replaceAll with regex
const regex = /Dog/ig;
console.log(p.replaceAll(regex, 'ferret'));
// expected output: "The quick brown fox jumps over the lazy ferret. If the ferret reacted, was it really lazy?"

Sub string

There are several methods to extract a port of a string, substring and slice are almost identical except some subtle differences if start is greater than end, or there are negative arguments:

  • substring(start[, end]), if start is greater than end, substring swaps the two argument.
  • slice(begin[, end]), if begin is greater than (or equal) end, it returns an empty string. If end is negative, it is treated as str.length + endIndex.
  • substr(start[, length]), a legacy feature in ECMAScript. It’s best to avoid using it if possible.

Differences between substring() and slice():

const str = 'Hello';

// If start is greater than end.
console.log(str.substring(5, 2));  // "llo"
console.log(str.slice(5, 2));      // ""

// Negative values.

// Negative start is treated as 0 for substring().
console.log(str.substring(-3, 3));  // "Hel"
// Negative start is treated as str.length -start for slice().
console.log(str.slice(-3, 3));      // "l"

// Negative end is treated as 0;
console.log(str.substring(0, -2)); // ""
// Negative end is treated as str.length + endIndex for slice().
console.log(str.slice(0, -2));     // "Hel"

substring()

The substring(start[, end]) returns the part of the string between the start and end indexes, or to the end of the string.

const str = 'Hello';

console.log(str.substring(1, 3)); // "el"
console.log(str.substring(2));    // "llo"
console.log(str.substring(0, 100)); // "Hello"

// Negative argument is treated as 0.
console.log(str.substring(-3));     // "Hello"
console.log(str.substring(-3, 3));  // "Hel"

// If start is greater than end, the effect of substring() is
// as if the two arguments were swapped.
console.log(100, 1);   // "ello"
console.log(100, 10);  // ""
console.log(100, 200); // ""

// NaN is treated as 0.
console.log(str.substring('a', 0));  // "H"
console.log(str.substring(0, 'a')); // ""

slice()

const str = 'Hello';

console.log(str.slice(1, 3));   // "el"
console.log(str.slice(2));      // "llo"
console.log(str.slice(0, 100)); // "Hello"

console.log(str.slice(-3));     // "llo"
console.log(str.slice(-3, 3));  // "l"

// NaN is treated as 0.
console.log(str.slice('a', 0));  // "H"
console.log(str.slice(0, 'a')); // ""

substr() (a legacy feature)

substr(start[, length]) returns a portion of the string, starting from the start index and extending for characters of length or ones to the end if length is not specified.

const str = 'Hello';

console.log(str.substr(1, 2)); // "el"
console.log(str.substr(2));    // "llo"

console.log(str.substr(-3));     // "llo"
console.log(str.substr(-3, 2));  // "ll"

// The value of start is capped at str.length if its value is out of range.
console.log(str.substr(-100, 2));// "He"

// If length is negative, it is reated as 0
console.log(str.substr(-3, -2)); // ""
console.log(str.substr(1, -2));  // ""

Search

includes()

The includes(searchString[, position]) method performs a case-sensitive search to determine whether one string may be found within another string, returning true or false as appropriate.

  • position, the position within the string at which to begin searching for searchString. (Defaults to 0.)
const sentence = 'The quick brown fox jumps over the lazy dog.';
const word = 'fox';

console.log(sentence.includes(word)); // true
console.log(sentence.includes(word, 20)); // false

search()

The search(regexp) method executes a search for a match between a regular expression and this String object.

If a non-RegExp object regexp is passed, it is implicitly converted to a RegExp with new RegExp(regexp).

const paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';

// any character that is not a word character or whitespace
const regex = /[^ws]/g;

console.log(paragraph.search(regex));
// expected output: 43

console.log(paragraph[paragraph.search(regex)]);
// expected output: "."

Split

split()

The split([separator[, limit]) method divides a String into an ordered list of substrings, puts these substrings into an array, and returns the array.

  • separator, the separator can be a simple string or it can be a regular expression.
  • limit, the number of substrings to be included in the array. If it is 0, [] is returned.
const str = 'Welcome to JavaScript world.';

const words = str.split(' '); // words: ["Welcome","to","JavaScript","world."]

const chars = str.split('');
// chars: ["W","e","l","c","o","m","e"," ","t","o"," ","J","a","v","a","S","c","r","i","p","t"," ","w","o","r","l","d","."]

const strCopy = str.split(); // strCopy: ["Welcome to JavaScript world."]

To string

toString()

The toString() method returns a string representing the specified object.

const stringObj = new String('foo');

console.log(stringObj);
// expected output: String { "foo" }

console.log(stringObj.toString());
// expected output: "foo"

Trim

To remove whitespace from both or either of the ends of a string. Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).

const greeting = '   Hello world!   ';

console.log(greeting);             // expected output: "   Hello world!   ";

// To remove whitespace from both ends.
console.log(greeting.trim());      // expected output: "Hello world!";

// To remove whitespace from the beginning
console.log(greeting.trimStart()); // expected output: "Hello world!

// To remove whitespace from the end
console.log(greeting.trimEnd());   // expected output: "   Hello world!";

valueOf

valueOf()

The valueOf() method returns the primitive value of a String object.

const stringObj = new String('foo');

console.log(stringObj);
// expected output: String { "foo" }

console.log(stringObj.valueOf());
// expected output: "foo"

Char Unicode

Unicode to char

The static String.fromCharCode() method returns a string created from the specified sequence of UTF-16 code units.

console.log(String.fromCharCode(189, 43, 190, 61));
// expected output: "½+¾="

It accept a sequence of numbers that are UTF-16 code units. The range is between 0 and 65535 (0xFFFF). Numbers greater than 0xFFFF are truncated. No validity checks are performed.

Char to Unicode

The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.

const sentence = 'The quick brown fox jumps over the lazy dog.';

const index = 4;

console.log(`The character code ${sentence.charCodeAt(index)} is equal to ${sentence.charAt(index)}`);
// expected output: "The character code 113 is equal to q"

Reference

JavaScript Array Operations with Examples

This article illustrates the operations of JavaScript Array. These examples include built-in APIs and some custom functions, such as groupBy, union, objectToArray, etc.

Note if fruits is not initialized in examples, it is:

let fruits = ['Apple', 'Banana'];

Basic operations

Create

let fruits = ['Apple', 'Banana'];
let length = fruits.length;
// 2

let fruits1 = [];
fruits1.push('Apple'); // ['Apple']
fruits1.push('Banada');// ['Apple', 'Banana'];

let fruits2 = new Array('Apple', 'Banana');

// Creates an array of 2 empty slots, not slots with actual undefined values
let fruit3 = new Array(2);
console.log(fruits3);
// Array [undefined, undefined]

Create an two-dimensional array

let board = [
    ['A0','A1','A2'],
    ['B0','B1','B2'],
    ['C0','C1','C2']
];

Set values

Set values directly

let fruits = ['Apple', 'Banana'];
fruits[1] = 'Blackberry';

If you set a value at a new indexed position which is not contained in the array. The length of the array will be updated accordingly.

let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits));  // ['0', '1', '4']

**Fill values **

The fill() method fills (modifies) all the elements of an array from a start index (default zero) to an end
index (default array length) with a static value. It returns the modified array.

Syntax: fill(value[, start[, end]])

let array1 = [1, 2, 3, 4];

// fill with 0 from position 2 until position 4
console.log(array1.fill(0, 2, 4));
// expected output: [1, 2, 0, 0]

// fill with 5 from position 1
console.log(array1.fill(5, 1));
// expected output: [1, 5, 5, 5]

console.log(array1.fill(6));
// expected output: [6, 6, 6, 6]

Access

length

console.log(fruits.length);

[] operator

Access an element through index

let first = fruits[0];
// Apple

let last = fruits[fruits.length - 1];
// Banana

Note: It is possible to quote the array indexes, such as fruits['0'], although it is not necessary. The 0 in fruits[0] is coerced into a string by the JavaScript engine through an implicit toString conversion.

Add, change

push() – Add to the end

// push() changes the length and returns the new length
let newLength = fruits.push('Coconut'); // ["Apple", "Banana", "Coconut"]
// 3

unshift() – Add to the front

// unshift() changes the length and returns the new length
let newLength = fruits.unshift('Avocado');// ["Avocado", "Apple", "Banana"];
// 3

[] operator – Add by setting a value at a new index position

let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits));  // ['0', '1', '4']

When setting a property on a JavaScript array when the property is an valid array index and that index is outside the current bounds of the array, the engine will update the array’s length property accordingly.

splice() – Add value of a specific position

The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. It returns an array containing the deleted elements.

let arrDeletedItems = arr.splice(start[, deleteCount[, item1[, item2[, ...]]]])
  • start

    The index at which to start changing the array.

  • deleteCount

    The number of elements in the array to remove from start.

  • item1, item2, ...

    The elements to add to the array, beginning from start. If you do not specify any elements, splice() will only remove elements from the array.

Example

let fruits = ['Apple', 'Banada', 'Coconut'];

// Remove 0 item from index of 1, and adding new item 'Blueberry'
let deletedItems = fruits.splice(1, 0, 'Blueberry'); // Add at index
// deletedItems: []
// fruits: ['Apple', 'Blueberry', Banada', 'Coconut']

Delete, remove

Delete from the end of an array

The pop() method removes the last element from an array and returns that element. This method changes the length of the array.

It returns undefined if the array is empty.

// pop() returns the removed element, it changes the length
// remove Banada from the end
let last = fruits.pop(); // ["Apple"];
// Banada

Delete from the front of an array

// shift() returns the removed element, it changes the length
// remove Apple from the front
let first = fruits.shift(); // ["Banana"];
// Apple

Delete elements from any position of an array

The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. It can be used to remove elements from any position.

let fruits = ['Apple', 'Banada', 'Coconut', 'Durian'];

// Delete fruits[1] and fruits[2]
let removed = fruits.splice(1, 2); // fruits: ['Apple', 'Durian']
console.log(removed); // ['Banada', 'Coconut']

Loop

There are several ways to loop over an array. Use mapreducefilter functions first if they satisfy your needs, otherwise use below loop operations. Although these function are slower, they are easier to code、read , maintain and test. See for vs for each vs (map, reduce, filter, find) for details.

Use for loop

for (let i = 0; i < furits.length; ++i) {
    console.log(furits[i]);
}

Use forEach method

The forEach() method executes a provided callback function once for each array element.

// The parameters of index and array are optional
fruits.forEach(function(currenValue, index, array) {
    console.log(curentValue, index);
});
// "Apple" 0
// "Banada" 1

Note: It is not invoked for index properties that have been deleted or are uninitialized. For example:

“`javascript
const arraySparse = [1,3,,7];
let numCallbackRuns = 0;

arraySparse.forEach(function (element) {
console.log(element);
numCallbackRuns++;
});
console.log(arraySparse); // 3
“`

Formatted print

Use console.table

console.table displays tabular data as a table. This feature is available in Web Workers.

console.table(['Apple', 'Banada']);
console.table(board); // prints a two-demensional array

Write your own function

function printArrayElements(element, index, array) {
    console.log('a[' + index + '] = ' + element);
}

fruits.forEach(printArrayElements);
// a[0] = "Apple"
// a[1] = "Banada"

Other Operations

Copy

Copy to a new array

The slice(begin, end) method returns a shallow copy of a portion of an array into a new array object (end not included) . The original array will not be modified.

let fruits = ['Apple', 'Banada'];
let shallowCopy = fruits.slice(); // this is how to make a copy
// ["Apple", "Banada"]

Syntax: slice([begin[, end]]).

Copy elements to the same array

The copyWithin(target, start, end) method shallow copies part of an array to target location in the same array and returns it without modifying its length.

Syntax: copyWithin(target[, start[, end]]).

let array1 = ['a', 'b', 'c', 'd', 'e'];

// copy to index 0 the element at index 3
console.log(array1.copyWithin(0, 3, 4));
// expected output: Array ["d", "b", "c", "d", "e"]

// copy to index 1 all elements from index 3 to the end
console.log(array1.copyWithin(1, 3));
// expected output: Array ["d", "d", "e", "d", "e"]

Filter

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

let fruits = ['Apple', 'Banana', 'Blueberry'];
let bfruits = fruits.filter(val => val.startsWith('B'));
// ['Banana', 'Blueberray']

Find

findIndex()

The findIndex() method returns the index of the first element in the array that satisfies the provided testing function.

Syntax

arr.findIndex(callback( element[, index[, array]] )[, thisArg])

Parameters

  • callback

    A function to execute on each value in the array until the function returns true, indicating that the satisfying element was found.

    It takes three arguments:

    • element

    The current element being processed in the array.

    • index Optional

    The index of the current element being processed in the array.

    • array Optional

    The array findIndex() was called upon.

  • thisArg Optional

    Optional object to use as this when executing callback.

Examples

let furits = ['Apple', 'Banana'];

function startsWithB(element) {
   return element.startsWith('B');
}

console.log(fruits.findIndex(startsWithB));
// expected output: 1

find()

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

let array1 = [5, 12, 8, 130, 44];

let elemnent = array1.find(function(element) {
    return element > 10;
});

console.log(element);
// 12

indexOf()

Get index of an element

The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

Syntax

arr.indexOf(searchElement[, fromIndex])

Parameters

  • searchElement

    Element to locate in the array.

  • fromIndex Optional

    The index to start the search at. If the index is greater than or equal to the array’s length, -1 is returned, which means the array will not be searched. If the provided index value is a negative number, it is taken as the offset from the end of the array. Note: if the provided index is negative, the array is still searched from front to back. If the provided index is 0, then the whole array will be searched. Default: 0 (entire array is searched).

indexOf() compares searchElement to elements of the Array using strict equality (the same method used by the === or triple-equals operator).

Examples

let array = [2, 9, 9];
array.indexOf(2);     // 0
array.indexOf(7);     // -1
array.indexOf(9, 2);  // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

includes()

Check whether an array includes a certain value

The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.

Syntax: includes(valueToFind[, fromIndex])

let fruits = ['Apple', 'Banana'];
console.log(fruits.includes('Orange'));// false
console.log(fruits.includes('App'));// false

Note: When comparing strings and characters, includes() is case-sensitive.

Note: Technically speaking, includes() uses the sameValueZero algorithm to determine whether the given element is found.

Join

The join(sperator) method creates and returns a new string by concatenating all of the elements in an array (or an array-like object), separated by commas or a specified separator string

let fruits = ['Apple', 'Banada'];

console.log(fruits.join());
// expected output: "Apple,Banada"

console.log(elements.join('-'));
// expected output: "Apple-Banada"

let board = [
  ['A','B','C'],
  ['D','E','F'],
  ['G','H','I']
];
console.log(board.join('n'));
// Output:
/*
A,B,C
D,E,F
G,H,I
*/

Merge / Concat

The concat()method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

let array1 = ['a', 'b', 'c'];
let array2 = ['d', 'e', 'f'];

console.log(array1.concat(array2));
// Array ["a", "b", "c", "d", "e", "f"]

Sort

Reverse

The reverse() method reverses an array in place. The first array element becomes the last, and the last array element becomes the first.

let array1 = ['one', 'two', 'three'];
let reversed = array1.reverse();
console.log(array1); // Array ['three', 'two', 'one']
console.log(reversed); // Array ['three', 'two', 'one']

Check/Test

Every: Test whether all elements pass provided function

The every() method tests whether all elements in the array pass the test implemented by the provided function.

function isBelowThreshold(currentValue) {
    return currentValue < 40;
}

let array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// true

Note: This method returns true for any condition put on an empty array.

Some: Test whether at least some elements pass provided function

The some() method tests whether at least one element in the array passes the test implemented by the provided function.

let even = function(element) {
    // checks whether an element is even
    return element % 2 === 0;
};

let array = [1, 2, 3, 4, 5];
console.log(array.some(even));
// true

Note: This method returns false for any condition put on an empty array.

isArray

The Array.isArray() method determines whether the passed value is an Array.

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

isArray vs instance of

When checking for Array instance, Array.isArray is preferred over instanceof because it works through iframes.

String to Array, Map to Array, Set to Array

(Array.from('foo'));
// ['f', 'o', 'o']

The Array.from() method creates a new, shallow-copied Array instance from an array-like or iterable object.

Array.from() lets you create Arrays from:

  • array-like objects (objects with a length property and indexed elements) or
  • iterable objects (objects where you can get its elements, such as Map and Set)
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// ['foo', 'bar', 'baz']

Other loops: map vs reduce

map

map() method creates a new array with the results of calling a provided function on every element in the calling array.

Syntax:

let new_array = arr.map(function callback(currentValue[, index[, array]]) {
    // Return element for new_array
}[, thisArg]
  • currentValue, the current value in the array
  • index
  • array, the array itself
  • thisArg, Value to use as this when executing callback.

Examples:

[1, 4, 9].map((val) => {
  return val * 2;
});
// It creates a new array: [2, 8, 18]

reduce

The reduce() method executes a callback on each element of the array, resulting in a single output value.

Syntax:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
  • accumulator

    The accumulator accumulates the callback’s return values. It is the accumulated value previously returned in the last invocation of the callback, or initialValue.

  • currentValue, the current element being processed in the array.

  • index, the index of the current element being processed in the array.

  • array, the array reduce() was called upon.

  • initialValue

    A value to use as the first argument to the first call of the callback. If no initialValue is supplied, the first element in the array will be used and skipped. Calling reduce() on an empty array without an initialValue will throw a TypeError.

Examples:

// Get sum of an array
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
  return accumulator + currentValue;
});

Custom operations

Filter an Objects Array by fields

filter is an object which defines the filter condition. If an object in the array has the properties with the same values in filter, it will be filtered out.

const filterArray = (arr, filter) => {
  var data = [];
  for (let obj of arr) {
    let filtered = true;
    for (let p in filter) { // for each property in filter
      if (obj[p] != filter[p]) {
        filtered = false;
        break;
      }
    }

    if (filtered) {
      data.push(obj);
    }
  } // for

  return data;
}

Examples:

let employees = [
    {name: 'Jane', gender: 'Female'},
    {name: 'Jim', gender: 'Male' },
    {name: 'Lily', gender: 'Female'}
};
filterArray(employees, {gender: 'Female'});
// [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}]

GroupBy

The following groupBy groups objects in an array by a field.

const groupBy = (arr, field) => {
    return arr.reduce(function (acc, obj) {
        let key = obj[field];
        acc[key] = acc[key] || [];
        acc[key].push(obj);
        return acc;
    }, {});
}

Examples:

let employees = [
  {name: 'Jane', gender: 'Female'},
  {name: 'Jim', gender: 'Male' },
  {name: 'Lily', gender: 'Female'}
];
groupBy(employees, 'gender');
// {
//   'Female': [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
//   'Male': [{name: 'Jim', gender: 'Male' }]
// }

If you want an array of grouped objects:

const groupBy = (arr, field) => {
    let groups = arr.reduce((acc, obj) => {
        let key = obj[field];
        acc[key] = acc[key] || [];
        acc[key].push(obj);
        return acc;
    }, {});

    return Object.keys(groups).map( group => {
        return groups[group];
    });
}

The result will be:

// [
//   [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
//   [{name: 'Jim', gender: 'Male' }]
// ]

A more generic version

Below code (from javascript codesnipt) is a more generic version. It accepts an array of basic types or objects. It has 2 processes:

  1. Use map to generate a new array. Here arr is the array, and f can be a function or a field name by which it is grouped.
  2. Use reduce function to produce a object in which a field indicates a group.
const groupBy = (arr, f) =>
    arr.map(typeof f === 'function' ? f : val => val[f]).reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
    }, {});

Examples:

groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}
groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}

Of course it can be completed in one loop:

const groupBy = (arr, f) => {
    return arr.reduce((acc, val) => {
        let key = (typeof f === 'function') ? f(val) : val[f]).
        acc[key] = acc[key] || [];
        acc[key].push(val);
        return acc;
    }, {});
}

Union

Union operation returns each item in any of a and b once.

const union = (a, b) => Array.from(new Set([...a, ...b]));

Examples:

union([1, 2, 3], [4, 3, 2]);
// [1,2,3,4]

The union above works only for primitive types. You can provides a comparison function to union other types.

const unionWith = (a, b, comp) =>
    Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));

It filters the elements that does not appear in a from b, then makes a merge operation.

Array to Set

let set = new Set(['Apple', 'Banana', 'Apple']);
// ('Apple', 'Banana')

Unique Values in Array

const uniqueValues(arr) => [...new Set(arr)];

shuffle

The modern version implemented in JavaScript of this algorithm (Fisher-Yates Algorithm, from the book The Art of Computer Programming by Donald E. Knuth) goes like:

for(let i = array.length — 1; i > 0; i--){
    const j = Math.floor(Math.random() * i)
    const temp = array[i]
    array[i] = array[j]
    array[j] = temp
}

The Phaser’s shuffle method also uses this algorithm, the source code:

var Shuffle = function (array)
{
    for (var i = array.length - 1; i > 0; i--)
    {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    return array;
};

Note

Below are two examples of when a random algorithm is not random enough:

  • Flaw #1: An Off-by-One Error

    random(n) returns a number between 0 and (n-1), therefore it will never swap the 52nd card with itself; the 52nd card can never end up in the 52nd place.

  • Flaw #2: The Shuffle Isn’t Uniform

    It swaps the ith card with a random card selected from the entire deck. A proper algorithm will swap the ith card only with a card in the interval(i, n) so that each element for a random swap only once.

  • Flaw #3: Using a 32-bit Seed

  • Flaw #4: Using the System Clock as a Seed

And words from Robert Sedgewick, author of Algorithms:

"That's a pretty tough thing to have happen if you're implementing online poker. You might want to make sure that if you're advertising that you're doing a random shuffle that you go ahead and do so."—Robert Sedgewick, Professor of Computer Science, Princeton

When Random Isn’t Random Enough: Lessons from an Online Poker Exploit

This example comes from a 1999 popular online poker platform implemented card-shuffling software. The algorithm used in the shuffling the 52 cards not random engouth:

{ Generate a new seed based on the system clock }
randomize;
{ Randomly rearrange each card }
for ctr := 1 to 52 do begin
random_number := random(51)+1;
tmp := card[random_number];
card[random_number] := card[ctr];
card[ctr] := tmp;
end;

How To Correctly Shuffle An Array in JavaScript

Microsoft had this browser ballot screen on browserchoice.eu where Microsoft was supposed to show all the different browser choices to users in random order. Here is the code they used for doing the random shuffle:

array.sort(function (a, b) { return 0.5 — Math.random() })

But the algorithm was far from random. Here’s an interesting statistical analysis on the results of this algorithm.

More this sort function is also very inefficient, for it gives a very inconsistent ordering which could go into an infinite loop or stop after a few exchanges.

Object to Array

This operation convert an object to an array.

let objectToArray = obj => {
    Object.keys(obj).map(val => {
        return obj[val];
    }
}

Use Array as object to store other properties

An array can be used as an object to store other properties.

let fruits = ['Orange', 'Lemon'];
fruits.kind = 'citrus';

Output an two-dimensional array in a table format

Use join()

let board = [
  ['A','B','C'],
  ['D','E','F'],
  ['G','H','I']
];

console.log(board.join('n'));

Output

A,B,C
D,E,F
G,H,I

Use console.table()

let board = [
  ['A','B','C'],
  ['D','E','F'],
  ['G','H','I']
];

console.log(board.join('n'));

Output

(index) 0 1 2
0 “A” “B” “C”
1 “D” “E” “F”
2 “G” “H” “I”

Reference