ECMAScript: Collections

core-js uses native collections in most cases and only fixes methods / constructors where required; in old environments, it uses a fast polyfill (O(1) lookup).

Map

Modules

es.map, es.map.group-by, es.map.get-or-insert and es.map.get-or-insert-computed.

Built-ins signatures

class Map {
  constructor(iterable?: Iterable<[key, value]>): Map;
  clear(): void;
  delete(key: any): boolean;
  forEach(callbackfn: (value: any, key: any, target: any) => void, thisArg?: any): void;
  get(key: any): any;
  getOrInsert(key: any, value: any): any;
  getOrInsertComputed(key: any, callbackfn: (key: any) => any): any;
  has(key: any): boolean;
  set(key: any, val: any): this;
  values(): Iterator<value>;
  keys(): Iterator<key>;
  entries(): Iterator<[key, value]>;
  @@iterator(): Iterator<[key, value]>;
  readonly attribute size: number;
  static groupBy(items: Iterable, callbackfn: (value: any, index: number) => key): Map<key, Array<mixed>>;
}

Entry points

core-js(-pure)/es|stable|actual|full/map
core-js(-pure)/es|stable|actual|full/map/group-by
core-js(-pure)/es|stable|actual|full/map/get-or-insert
core-js(-pure)/es|stable|actual|full/map/get-or-insert-computed

Examples

let array = [1];

let map = new Map([['a', 1], [42, 2]]);
map.set(array, 3).set(true, 4);

map.size;        // => 4
map.has(array);  // => true
map.has([1]);    // => false
map.get(array);  // => 3
map.forEach((val, key) => {
  console.log(val);           // -> 1, 2, 3, 4
  console.log(key);           // -> 'a', 42, [1], true
});
map.delete(array);
map.size;        // => 3
map.get(array);  // => undefined
Array.from(map); // => [['a', 1], [42, 2], [true, 4]]

map = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (let [key, value] of map) {
  console.log(key);                                 // -> 'a', 'b', 'c'
  console.log(value);                               // -> 1, 2, 3
}
for (let value of map.values()) console.log(value); // -> 1, 2, 3
for (let key of map.keys()) console.log(key);       // -> 'a', 'b', 'c'
for (let [key, value] of map.entries()) {
  console.log(key);                                 // -> 'a', 'b', 'c'
  console.log(value);                               // -> 1, 2, 3
}

map = Map.groupBy([1, 2, 3, 4, 5], it => it % 2);
map.get(1); // => [1, 3, 5]
map.get(0); // => [2, 4]


map = new Map([['a', 1]]);

map.getOrInsert('a', 2); // => 1

map.getOrInsert('b', 3); // => 3

map.getOrInsertComputed('a', key => key); // => 1

map.getOrInsertComputed('c', key => key); // => 'c'

map; // => Map { 'a' => 1, 'b' => 3, 'c' => 'c' }

Set

Modules

es.set, es.set.difference.v2, es.set.intersection.v2, es.set.is-disjoint-from.v2, es.set.is-subset-of.v2, es.set.is-superset-of.v2, es.set.symmetric-difference.v2, es.set.union.v2.

Built-ins signatures

class Set {
  constructor(iterable?: Iterable<value>): Set;
  add(key: any): this;
  clear(): void;
  delete(key: any): boolean;
  forEach(callbackfn: (value: any, key: any, target: any) => void, thisArg?: any): void;
  has(key: any): boolean;
  values(): Iterator<value>;
  keys(): Iterator<value>;
  entries(): Iterator<[value, value]>;
  difference(other: SetLike<mixed>): Set;
  intersection(other: SetLike<mixed>): Set;
  isDisjointFrom(other: SetLike<mixed>): boolean;
  isSubsetOf(other: SetLike<mixed>): boolean;
  isSupersetOf(other: SetLike<mixed>): boolean;
  symmetricDifference(other: SetLike<mixed>): Set;
  union(other: SetLike<mixed>): Set;
  @@iterator(): Iterator<value>;
  readonly attribute size: number;
}

Entry points

core-js(-pure)/es|stable|actual|full/set
core-js(-pure)/es|stable|actual|full/set/difference
core-js(-pure)/es|stable|actual|full/set/intersection
core-js(-pure)/es|stable|actual|full/set/is-disjoint-from
core-js(-pure)/es|stable|actual|full/set/is-subset-of
core-js(-pure)/es|stable|actual|full/set/is-superset-of
core-js(-pure)/es|stable|actual|full/set/symmetric-difference
core-js(-pure)/es|stable|actual|full/set/union

Examples

let set = new Set(['a', 'b', 'a', 'c']);
set.add('d').add('b').add('e');
set.size;        // => 5
set.has('b');    // => true
set.forEach(it => {
  console.log(it);            // -> 'a', 'b', 'c', 'd', 'e'
});
set.delete('b');
set.size;        // => 4
set.has('b');    // => false
Array.from(set); // => ['a', 'c', 'd', 'e']

set = new Set([1, 2, 3, 2, 1]);

for (let value of set) console.log(value);          // -> 1, 2, 3
for (let value of set.values()) console.log(value); // -> 1, 2, 3
for (let key of set.keys()) console.log(key);       // -> 1, 2, 3
for (let [key, value] of set.entries()) {
  console.log(key);                                 // -> 1, 2, 3
  console.log(value);                               // -> 1, 2, 3
}

new Set([1, 2, 3]).union(new Set([3, 4, 5]));               // => Set { 1, 2, 3, 4, 5 }
new Set([1, 2, 3]).intersection(new Set([3, 4, 5]));        // => Set { 3 }
new Set([1, 2, 3]).difference(new Set([3, 4, 5]));          // => Set { 1, 2 }
new Set([1, 2, 3]).symmetricDifference(new Set([3, 4, 5])); // => Set { 1, 2, 4, 5 }
new Set([1, 2, 3]).isDisjointFrom(new Set([4, 5, 6]));      // => true
new Set([1, 2, 3]).isSubsetOf(new Set([5, 4, 3, 2, 1]));    // => true
new Set([5, 4, 3, 2, 1]).isSupersetOf(new Set([1, 2, 3]));  // => true

WeakMap

Modules

es.weak-map, es.weak-map.get-or-insert and es.weak-map.get-or-insert-computed.

Built-ins signatures

class WeakMap {
  constructor(iterable?: Iterable<[key, value]>): WeakMap;
  delete(key: object | symbol): boolean;
  get(key: object | symbol): any;
  getOrInsert(key: object | symbol, value: any): any;
  getOrInsertComputed(key: object | symbol, callbackfn: (key: any) => any): any;
  has(key: object | symbol): boolean;
  set(key: object | symbol, val: any): this;
}

Entry points

core-js(-pure)/es|stable|actual|full/weak-map
core-js(-pure)/es|stable|actual|full/weak-map/get-or-insert
core-js(-pure)/es|stable|actual|full/weak-map/get-or-insert-computed

Examples

let a = [1];
let b = [2];
let c = [3];

let weakmap = new WeakMap([[a, 1], [b, 2]]);
weakmap.set(c, 3).set(b, 4);
weakmap.has(a);   // => true
weakmap.has([1]); // => false
weakmap.get(a);   // => 1
weakmap.delete(a);
weakmap.get(a);   // => undefined

// Private properties store:
let Person = (() => {
  let names = new WeakMap();
  return class {
    constructor(name) {
      names.set(this, name);
    }
    getName() {
      return names.get(this);
    }
  };
})();

let person = new Person('Vasya');
person.getName(); // => 'Vasya'

WeakSet

Modules

es.weak-set.

Built-ins signatures

class WeakSet {
  constructor(iterable?: Iterable<value>): WeakSet;
  add(key: object | symbol): this;
  delete(key: object | symbol): boolean;
  has(key: object | symbol): boolean;
}

Entry points

core-js(-pure)/es|stable|actual|full/weak-set

Examples

let a = [1];
let b = [2];
let c = [3];

let weakset = new WeakSet([a, b, a]);
weakset.add(c).add(b).add(c);
weakset.has(b);   // => true
weakset.has([2]); // => false
weakset.delete(b);
weakset.has(b);   // => false

Warning

  • Weak-collections polyfill stores values as hidden properties of keys. It works correctly and does not leak in most cases. However, it is desirable to store a collection longer than its keys.
  • Native symbols as WeakMap keys can't be properly polyfilled without memory leaks.