let and const Commands
// 1. Variables declared with `let` are only valid within the block they are defined in, preventing global pollution like `var`. `let` introduces block-level scoping.
// 2. No variable hoisting.
// 3. Duplicate declarations are not allowed.
let a = 10;// `const` declares a read-only constant. Once declared, its value cannot be changed.
const PI = 3.1415;JavaScript has a top-level object providing the global environment (global scope) where all code runs. However, this top-level object varies across implementations:
- In browsers, the top-level object is
window, but Node and Web Workers do not havewindow. - In browsers and Web Workers,
selfpoints to the top-level object, but Node does not haveself. - In Node, the top-level object is
global, but other environments do not support it.
To access the top-level object across environments, this is commonly used, but it has limitations:
- In the global environment,
thisreturns the top-level object. In Node modules and ES6 modules,thisreturns the current module. - Inside functions, if the function is not run as an object method but as a standalone function,
thispoints to the top-level object. In strict mode,thisisundefined. - In both strict and non-strict modes,
new Function('return this')()always returns the global object. However, if the browser uses CSP (Content Security Policy), methods likeevalandnew Functionmay be unavailable.
// Accessing the top-level object
// Method 1
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// Method 2
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};Variable Destructuring Assignment
Array Destructuring
let [a, b, c] = [1, 2, 3]; // If destructuring fails, the variable's value is `undefined`.
let [a, [b], d] = [1, [2, 3], 4];
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2Object Destructuring
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; // If destructuring fails, the variable's value is `undefined`.
let { log, sin, cos } = Math;
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
const node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
let { loc, loc: { start }, loc: { start: { line }} } = node;String Destructuring
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5Numeric and Boolean Destructuring
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // trueFunction Parameter Destructuring
function add([x, y]) {
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);Use Cases
// Swap variable values
let x = 1;
let y = 2;
[x, y] = [y, x];
// Return an array
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// Return an object
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
// Ordered parameters
function f([x, y, z]) { ... }
f([1, 2, 3]);
// Unordered parameters
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
// Extract JSON data
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
// Iterate over Map structure
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// Import specific module methods
const { SourceMapConsumer, SourceNode } = require("source-map");String Extensions
Template literals allow embedding variables within ${}:
// Regular string
`In JavaScript '\n' is a line-feed.`
// Multiline string
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
// Embed variables
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// Nested function in template literal
function fn() {
return "Hello World";
}
`foo ${fn()} bar`New String Methods
String.fromCodePoint(): Returns a character from a Unicode code point, but cannot handle code points greater than0xFFFF.String.raw(): Returns a string with escaped slashes (adds a slash before each slash), often used for template literal processing.String.codePointAt(): Returns the code point of a character.String.normalize(): Unifies different representations of a character into a standard form (Unicode normalization).String.includes(): Returns a boolean indicating whether the parameter string is found.String.startsWith(): Returns a boolean indicating whether the parameter string is at the start.String.endsWith(): Returns a boolean indicating whether the parameter string is at the end.String.repeat(): Returns a new string repeating the original stringntimes.String.padStart(): Pads the start of a string; first parameter is the maximum length, second is the padding string.String.padEnd(): Pads the end of a string; first parameter is the maximum length, second is the padding string.String.trimStart(): Removes leading spaces.String.trimEnd(): Removes trailing spaces.String.matchAll(): Returns all matches of a regular expression in the string.
Regular Expression Extensions
RegExp Constructor
If the first argument to the RegExp constructor is a regular expression object, the second argument can specify modifiers. The returned expression ignores the original modifiers, using only the new ones.
new RegExp(/abc/ig, 'i').flags;
const regexGreekSymbol = /\p{Script=Greek}/u;
regexGreekSymbol.test('π') // true
// Match all numbers
const regex = /^\p{Number}+$/u;
regex.test('²³¹¼½¾') // true
regex.test('㉛㉜㉝') // true
regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true
// Match all spaces
\p{White_Space}
// Match all letters in various scripts, equivalent to Unicode \w
[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// Match all non-letters in various scripts, equivalent to Unicode \W
[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// Match Emoji
/\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu
// Match all arrow characters
const regexArrows = /^\p{Block=Arrows}+$/u;
regexArrows.test('←↑→↓↔↕↖↗↘↙⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩') // trueNamed Capture Groups
ES2018 introduced named capture groups, allowing each group to have a specified name.
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');Regular Expression Match Indices
const text = 'zabbcdef';
const re = /ab/;
const result = re.exec(text);
result.index // 1
result.indices // [ [1, 3] ]
const text = 'zabbcdef';
const re = /ab+(?<Z>cd)/;
const result = re.exec(text);
result.indices.groups // { Z: [ 4, 6 ] }String.prototype.matchAll()
ES2020 introduced String.prototype.matchAll(), which retrieves all matches at once, returning an iterator rather than an array.
const string = 'test1test2test3';
// The `g` modifier is optional
const regex = /t(e)(st(\d?))/g;
for (const match of string.matchAll(regex)) {
console.log(match);
}
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
// Convert to array (Method 1)
[...string.matchAll(regex)]
// Convert to array (Method 2)
Array.from(string.matchAll(regex))String Regular Expression Methods
Strings have four methods that use regular expressions: match(), replace(), search(), and split(). ES6 ensures these methods internally call RegExp instance methods, centralizing all regex-related functionality on the RegExp object:
String.prototype.matchcallsRegExp.prototype[Symbol.match]String.prototype.replacecallsRegExp.prototype[Symbol.replace]String.prototype.searchcallsRegExp.prototype[Symbol.search]String.prototype.splitcallsRegExp.prototype[Symbol.split]
RegExp.prototype.unicode Property
The unicode property on regex instances indicates whether the u modifier is set.
const r1 = /hello/;
const r2 = /hello/u;
r1.unicode // false
r2.unicode // trueRegExp.prototype.sticky Property
The sticky property indicates whether the y modifier is set.
var r = /hello\d/y;
r.sticky // trueRegExp.prototype.flags Property
The flags property returns the modifiers of a regular expression.
// ES5 source property returns the regex pattern
/abc/ig.source
// "abc"
// ES6 flags property returns the regex modifiers
/abc/ig.flags
// 'gi'Numeric Extensions
Binary and Octal Notation
ES6 introduced new notations for binary (0b or 0B) and octal (0o or 0O) numbers.
0b111110111 === 503 // true
0o767 === 503 // trueNumber.isFinite(), Number.isNaN()
Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true
isFinite(25) // true
isFinite("25") // true
Number.isFinite(25) // true
Number.isFinite("25") // falseNumber.parseInt(), Number.parseFloat()
// ES5
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45
// ES6
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45
Number.parseInt === parseInt // true
Number.parseFloat === parseFloat // trueNumber.isInteger()
Number.isInteger(25) // true
Number.isInteger(25.1) // false
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // false
Number.isInteger(5E-324) // false
Number.isInteger(5E-325) // trueNumber.EPSILON
Number.EPSILON === Math.pow(2, -52)
// true
Number.EPSILON
// 2.220446049250313e-16
Number.EPSILON.toFixed(20)
// "0.00000000000000022204"Safe Integers and Number.isSafeInteger()
Number.isSafeInteger() checks if an integer is within the safe range.
Number.isSafeInteger('a') // false
Number.isSafeInteger(null) // false
Number.isSafeInteger(NaN) // false
Number.isSafeInteger(Infinity) // false
Number.isSafeInteger(-Infinity) // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1) // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER) // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER) // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1) // falseMath Object Extensions
// Math.trunc removes the decimal part, returning the integer part.
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
// Math.sign determines if a number is positive, negative, or zero.
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
// Math.cbrt computes the cube root.
Math.cbrt(-1) // -1
Math.cbrt(0) // 0
Math.cbrt(1) // 1
// Math.clz32 converts to a 32-bit unsigned integer and counts leading zeros.
Math.clz32(0) // 32
Math.clz32(1) // 31
Math.clz32(1000) // 22
// Math.imul multiplies two numbers as 32-bit signed integers.
Math.imul(2, 4) // 8
Math.imul(-1, 8) // -8
Math.imul(-2, -2) // 4
// Math.fround returns a number in 32-bit single-precision float format.
Math.fround(0) // 0
Math.fround(1) // 1
Math.fround(2 ** 24 - 1) // 16777215
// ES6 added four logarithmic methods
Math.expm1()
Math.log1p()
Math.log10()
Math.log2()
// Hyperbolic functions
Math.sinh(x)
Math.cosh(x)
Math.tanh(x)
Math.asinh(x)
Math.acosh(x)
Math.atanh(x)Exponentiation Operator
ES2016 introduced the exponentiation operator (**).
2 ** 2 // 4
2 ** 3 // 8BigInt Data Type
ES2020 introduced BigInt to handle large integers with unlimited precision.
const a = 2172141653n;
const b = 15346349309n;
// BigInt maintains precision
a * b // 33334444555566667777n
// Regular integers lose precision
Number(a) * Number(b) // 33334444555566670000BigInt values must have an n suffix.
1234 // Regular integer
1234n // BigInt
// BigInt operations
1n + 2n // 3n
0b1101n // Binary
0o777n // Octal
0xFFn // HexadecimalThe BigInt constructor converts values to BigInt, similar to Number().
BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n
const max = 2n ** (64n - 1n) - 1n;
BigInt.asIntN(64, max)
// 9223372036854775807n
BigInt.asIntN(64, max + 1n)
// -9223372036854775808n
BigInt.asUintN(64, max + 1n)
// 9223372036854775808n
Boolean(0n) // false
Boolean(1n) // true
Number(1n) // 1
String(1n) // "1"Function Extensions
Default Parameter Values
function Point(x = 0, y = 0) {
this.x = x;
this.y = y;
}
let x = 99;
function foo(p = x + 1) {
console.log(p);
}Rest Parameters
ES6 introduced rest parameters (...variableName) to capture excess arguments as an array, eliminating the need for arguments.
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10Strict Mode
ES6 prohibits explicitly enabling strict mode in functions with default values, destructuring, or spread operators.
// Error
function doSomething(a, b = a) {
'use strict';
// code
}
// Error
const doSomething = function ({a, b}) {
'use strict';
// code
};
// Error
const doSomething = (...a) => {
'use strict';
// code
};
const obj = {
// Error
doSomething({a, b}) {
'use strict';
// code
}
};name Property
The name property in ES6 returns the actual function name.
var f = function () {};
// ES5
f.name // ""
// ES6
f.name // "f"Arrow Functions
var f = () => 5;
// Equivalent to
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// Equivalent to
var sum = function(num1, num2) {
return num1 + num2;
};
var sum = (num1, num2) => { return num1 + num2; }Tail Call Optimization
A tail call occurs when a function’s last action is calling another function.
function f(x) {
return g(x);
}Trailing Comma in Parameters
ES2017 allows a trailing comma in the last function parameter.
function clownsEverywhere(
param1,
param2,
) { /* ... */ }
clownsEverywhere(
'foo',
'bar',
);Function.prototype.toString()
The toString() method now returns the exact function code, including comments and spaces.
function /* foo comment */ foo () {}
foo.toString()
// function /* foo comment */ foo () {}Optional catch Parameter
try {
// ...
} catch {
// ...
}Array Extensions
Spread Operator
The spread operator (...) is the inverse of rest parameters, converting an array into a comma-separated sequence.
function push(array, ...items) {
array.push(...items);
}
function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers) // 42
function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);Array.from()
Array.from() converts array-like objects and iterables (e.g., Set, Map) into true arrays.
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
Array.from([1, 2, 3])
// [1, 2, 3]Array.of()
Array.of() converts a set of values into an array.
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1Array.prototype.copyWithin()
Array.prototype.copyWithin(target, start = 0, end = this.length)
// Copy position 3 to position 0
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
// -2 corresponds to position 3, -1 to position 4
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]Array.prototype.find() and findIndex()
find() returns the first array element meeting the condition. findIndex() returns the index of the first matching element or -1 if none match.
[1, 4, -5, 10].find((n) => n < 0)
// -5
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2Array.prototype.fill()
fill() populates an array with a specified value.
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]Array.prototype.entries(), keys(), and values()
ES6 introduced entries(), keys(), and values() for array iteration, each returning an iterator.
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"Array.prototype.includes()
includes() returns a boolean indicating whether an array contains a given value.
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // trueArray.prototype.flat() and flatMap()
flat() flattens nested arrays into a single-level array. flatMap() maps each element and flattens the result.
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
// Equivalent to [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]Object Extensions
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"Object Destructuring
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
let newVersion = {
...previousVersion,
name: 'New Name' // Override the name property
};Optional Chaining Operator
const firstName = (message
&& message.body
&& message.body.user
&& message.body.user.firstName) || 'default';
const fooInput = myForm.querySelector('input[name=foo]')
const fooValue = fooInput ? fooInput.value : undefinedOptional chaining has three uses:
obj?.prop// Object propertyobj?.[expr]// Same as abovefunc?.(...args)// Function or object method call
New Object Methods
Object.is()
Compares two values for strict equality, similar to ===.
Object.is('foo', 'foo')
// true
Object.is({}, {})
// falseObject.assign()
Merges source objects’ enumerable properties into a target object.
const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
const obj = {a: 1};
Object.assign(obj) === obj // true// Object.assign performs shallow copying, not deep copying.
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2Common Use Cases
// Add properties to an object
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
// Add methods to an object
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
// ...
},
anotherMethod() {
// ...
}
});
// Clone an object
function clone(origin) {
return Object.assign({}, origin);
}
// Merge multiple objects
const merge =
(target, ...sources) => Object.assign(target, ...sources);
// Set default values for properties
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
console.log(options);
// ...
}Object.getOwnPropertyDescriptors()
Returns the descriptor objects for all own (non-inherited) properties of an object.
const obj = {
foo: 123,
get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
const source = {
set foo(value) {
console.log(value);
}
};
const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')proto, Object.setPrototypeOf(), Object.getPrototypeOf()
__proto__ reads or sets an object’s prototype. Object.setPrototypeOf() sets the prototype, returning the object itself. Object.getPrototypeOf() reads the prototype.
// ES5
const obj = {
method: function() { ... }
};
obj.__proto__ = someOtherObj;
// ES6
var obj = Object.create(someOtherObj);
obj.method = function() { ... };
// Syntax
Object.setPrototypeOf(object, prototype)
// Usage
const o = Object.setPrototypeOf({}, null);
function Rectangle() {
// ...
}
const rec = new Rectangle();
Object.getPrototypeOf(rec) === Rectangle.prototype
// true
Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// falseObject.keys(), Object.values(), Object.entries()
Iterate over objects.
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}Object.fromEntries()
The inverse of Object.entries(), converts an array of key-value pairs into an object.
// Example 1
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
Object.fromEntries(entries)
// { foo: "bar", baz: 42 }
// Example 2
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }Symbol
Represents a unique value, the seventh data type in JavaScript.
let mySymbol = Symbol();
// Method 1
let a = {};
a[mySymbol] = 'Hello!';
// Method 2
let a = {
[mySymbol]: 'Hello!'
};
// Method 3
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// All methods yield the same result
a[mySymbol] // "Hello!"
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefinedSet and Map Data Structures
Set
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
// Example 1
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
// Example 2
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
// Example 3
const set = new Set(document.querySelectorAll('div'));
set.size // 56
// Remove duplicates from an array
[...new Set(array)]
// Remove duplicates from a string
[...new Set('ababbc')].join('')
// "abc"WeakSet
WeakSet is similar to Set, storing unique values, but its members must be objects, and it holds weak references, meaning the garbage collector ignores WeakSet references.
WeakSet cannot be iterated because its members are weak references that may disappear at any time. It is useful for storing DOM nodes without risking memory leaks when nodes are removed.
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}
const obj = {};
const foo = {};
ws.add(window);
ws.add(obj);
ws.has(window); // true
ws.has(foo); // false
ws.delete(window);
ws.has(window); // falseMap
Map is a collection of key-value pairs, where keys can be any type, not just strings, offering a more robust hash structure than objects.
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // falseMap provides three iterator-generating methods and one traversal method:
Map.prototype.keys(): Returns an iterator for keys.Map.prototype.values(): Returns an iterator for values.Map.prototype.entries(): Returns an iterator for all entries.Map.prototype.forEach(): Iterates over all members.
Conversions with Other Data Structures
// Map to array
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
// Array to Map
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map to object
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
// Object to Map
let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj));
// Map to JSON
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
// JSON to Map
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}WeakMap
WeakMap is similar to Map but only accepts objects (except null) as keys, holding weak references.
WeakMap lacks iteration methods (keys(), values(), entries()) and the size property, and it cannot be cleared (clear()). Available methods are get(), set(), has(), and delete().
// Add members using set
const wm1 = new WeakMap();
const key = {foo: 1};
wm1.set(key, 2);
wm1.get(key) // 2
// Accept an array as constructor argument
const k1 = [1, 2, 3];
const k2 = [4, 5, 6];
const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
wm2.get(k2) // "bar"



