-Set, Map, (Weak), Symbol and BigInt

set and map: these two data structures should be constructed through new. The parameters received by two data structures, one is a one-dimensional array and the other is a two-dimensional array.

1, Set data structure

A Set is actually a data structure similar to an array. The difference is that there are no duplicate basic type values or reference type values with the same address in the members of Set (in short, it is similar to using Object.is() comparison).

Note: the internal comparison of Set is similar to that of Object.is(), but es6 has made some modifications to the comparison rules. For example, + 0 and - 0 will be de duplicated in Set, but Object.is() returns fasle

// Set(2) {0, NaN} false
let aSet = new Set([+0,-0,NaN,NaN]);
console.log(aSet,Object.is(+0,-0));

(1) Using Array.from() and set methods to realize array de duplication

let aset = new Set([1,2,1]);
Array.from(aset);

(2) Using extension operator and Set method to realize array de duplication

var arr = [1,2,1,11];
console.log([...new Set(arr)]); // (3)[1, 2, 11]

Difference between 0, set and array

  • (1) Key name: the key name and key value of set are the same.
  • (2) Get internal value: set cannot access the internal value through subscript like array, but must be obtained through traversal (usually forEach)
// demo1
let aSet = new Set([2,3,[4,5]]);
console.log(aSet[2]); // undefined

// demo2
let aSet = new Set([2,3,[4,5]]);
aSet.forEach((value, index, arr) => {
    console.log(value, index, arr); 
})
// 3 outputs: 
// 2 2 Set(3) {2, 3, Array(2)}
// 3 3 Set(3) {2, 3, Array(2)}
// [4,5] [4,5] Set(3) {2, 3, Array(2)}

1. Create set

Create directly with the new operator. Set can receive an array as a parameter. If there are duplicate basic type values or reference type values with the same address in this array, only one value will be retained. Moreover, set has a size attribute, which is used to indicate the number of data in set after de duplication.

// demo1
var aSet = new Set([1,2,1]);
typeof aSet, aSet, aSet.size // object   Set(2){1, 2}   2


// demo2
let aArr1 = [1,2],
    bArr1 = aArr1,
    cArr1 = [1,2];
let aSet = new Set([1,3,1,aArr1,bArr1,cArr1]); // Set(4)   {1, 3, Array(2), Array(2)}, bArr1 is ignored, and the two ARRS in the returned results are aArr1 and cArr1

2. set method

Operation method (for operating data)

  • (1)set.add(value): returns the modified set structure itself and modifies the original set. Add a data.
var aSet = new Set([1,2]);
// Set(5){1, 2, "a", Array(1), {...}}   Set(5){1, 2, "a", Array(1), {...}}
console.log(aSet.add('a').add([5]).add({o:"1"}),aSet);
  • (2)set.delete(value): returns a Boolean value indicating whether the deletion was successful. Delete the specified data. If you need to delete a reference type, you need to provide the address corresponding to the reference type to delete it
// demo1
var aSet = new Set([1,2]);
console.log(aSet.delete(1),aSet); // true Set(1){2}

// demo2, failed to delete reference type
let aSet = new Set([1,3,1,[1,2],[1,2]]);
console.log(aSet.delete([1,2]), aSet); // false Set(4) {1, 3, Array(2), Array(2)}

// demo3, deletion of reference type succeeded
let arr = [1,2];
let aSet = new Set([1,3,1,arr,[1,2,3]]);
console.log(aSet.delete(arr), aSet); // true Set(3) {1, 3, Array(3)}
  • (3)set.has(value): returns a Boolean value. Judge whether the value is a member of set.
var aSet = new Set([1,2]);
console.log(aSet.has(2),aSet); // true Set(2){1, 2}
  • (4)set.clear(): clear all data without return value

Traversal methods (used to traverse members), which are actually several traversal methods on the object

Note: the key name and value of the set structure are the same

  • (1)set.keys(): iterator object that returns the key name
  • (2)set.values(): iterator object that returns key values. Because the set structure has no key name or the key name and key value are the same, the two methods return the same value. The instance of the set structure is traversable by default, and its default iterator generating function is its values method. Therefore, you can omit the values method and directly use the for... Of loop to traverse the set
  • (3)set.entries(): iterator object that returns key value pairs. Since it also returns key value pairs, if you use for of to iterate over this value, you will output an array one at a time
var aSet = new Set([1,2]);
// SetIterator{1, 2} SetIterator{1, 2} SetIterator{1, 2} Set(2){1, 2}
console.log(aSet.keys(),aSet.values(),aSet.entries(),aSet);

for(var item of aSet.values()) {
  console.log(item); // 1    2
}

for(var item of aSet) {
  console.log(item); // 1    2
}

for(var item of aSet.entries()) {
  console.log(item); // [1,1]  [2,2]
}
  • (4)set.forEach(): This is actually similar to the forEach of the array. This method is generally used to obtain the internal value of the set structure
var aSet = new Set([2,3]);
aSet.forEach(function(currentValue,index,set){console.log(currentValue, index);}); 
// Two stage output
// 2 2
// 3 3

2, WeakSet data structure

  • The WeakSet structure is similar to Set, and it is also a collection of non duplicate values. However, it differs from Set as follows.
    • (1) Members of a weakset can only be objects, not values of other types.
    • (2) All object members in the WeakSet are weak references, that is, the reference of the object by the WeakSet is not included in the garbage collection mechanism (that is, the number of reference counts will not be increased by 1); That is, if other objects no longer reference the member object, the garbage collection mechanism will automatically reclaim the memory occupied by the object, regardless of whether the object still exists in the WeakSet
    • (3)WeakSet has only three methods: WeakSet.prototype.add(value), WeakSet.prototype.delete(value) and WeakSet.prototype.has(value)
    • (4)WeakSet has no way to traverse its members, that is, it has no size attribute and cannot use forEach
    • (4) One use of weakset is to store DOM nodes without worrying about memory leaks when these nodes are removed from the document
const ws = new WeakSet();
ws.add(1) // TypeError: Invalid value used in weak set
ws.add(Symbol()) // TypeError: invalid value used in weak set
ws.add(null); // report errors
ws.add({a:1}) // Successfully, the added member can only be an object
const ws = new WeakSet([3, 4]); // report errors,

const ws = new WeakSet([[1, 2], [3, 4]]); // Success, each item of the array can only be an object
ws.size // undefined.  WeakSet cannot access size
ws.forEach // undefined.  The WeakSet cannot be traversed using forEach
ws.forEach(function(item){ console.log('WeakSet has ' + item)}) // // TypeError: undefined is not a function

3, Map data structure

A Map (Dictionary) is actually a data structure similar to an object. The difference is that the key in the object can only be a string or Symbol, while the key in the Map can include various data types.

1. Create Map

Create directly with the new operator. Map can receive a two-dimensional array as a parameter. The first two items of the layer array in the two-dimensional array are the keys and values representing the created map (the redundant items behind the layer array are invalid). The map still has a size attribute to represent the number of data in the map

var aMap = new Map([['1',2,3],[2,3]]);
console.log(typeof aMap, aMap, aMap.size); // object   Map(2){"1" => 2, 2 => 3}   2

2. Map method

Operation method (used to operate data): compared with set, Map has more methods to obtain values map.get(), and more modification methods map.set()(set has only set.add() methods to add values)

  • (1)map.set(key,value): returns the modified map structure itself. If there is no key, create one
  • (2)map.get(key): returns the key value corresponding to the key. If it is not found, it returns undefined (no conversion will be made to the key)
var aMap = new Map([['1',2,3],[2,3]]);
console.log(aMap.set(2,4),aMap.get(2)); // Map(2){"1" => 2, 2 => 4}
console.log(aMap.get(1),aMap.get('1')); // undefined 2

let sym = Symbol.for('test');
let arr = [['a',1],['b',2],[sym,45]];
let map = new Map(arr);
// Get the key value as symbol
console.log(map.get(sym)); // 45
  • (3)map.delete(key): returns a Boolean value. Indicates whether the specified key was deleted successfully
  • (4)map.has(key): returns a Boolean value. Indicates whether the key is in the map
  • (5)map.clear(): no return value. Indicates that all data is cleared

Traversal method (used to traverse members)

  • (1)map.keys(): returns the Iterator object containing all key names. Array.form() or extension operator can directly convert Iterator object or map object into array. The Iterator object returned by keys and values will be converted into a one-dimensional array; The Iterator object returned by entries will be converted into a two-dimensional array; Converting a map object directly also returns a two-dimensional array
  • (2)map.values(): returns the iterator object containing all key values.
  • (3)map.entries(): returns the iterator object containing all key - value pairs
  • (4)map.forEach(): This is actually similar to the forEach of the array

Therefore, it is a good method to directly use Array.from() to build the Iterator object into an array and then traverse it. There is no need to remember other APIs

  • Judge Set and Map types
    • If typeof is directly used to judge Set or Map, the returned is Object
    • To judge the type of Set or Map, you need to use Object.prototype.toString.call(). The returned is [object Set]
const map = new Map();
map.set('a', 1)
map.set('b', 2)
map.set('c', 3)
map.forEach((value,index) => {console.log(value,index)}) // 1 "a", 2 "b", 3 "c"

const keysIterator = map.keys(); // MapIterator{"a", "b", "c"}
let tempArr = Array.from(keysIterator); // (3)["a", "b", "c"]
// The same effect can be achieved by using the extension operator above. Enter [... keysIterator]

const valuesIterator = map.values(); // MapIterator{1, 2, 3}
tempArr = Array.from(valuesIterator); // (3)[1, 2, 3]

const entriesIterator = map.entries(); // MapIterator{"a" => 1, "b" => 2, "c" => 3}
tempArr = Array.from(entriesIterator); // (3)[["a", 1], ["b", 2], ["c", 3]]

const f = Array.from(new Map([["a",2],["b",3]])); // [["a", 2], ["b", 3]], directly convert the map object into a two-dimensional array. However, Array.from cannot directly convert ordinary objects
const ff = Array.from({"a":2}); // [].  Array.from cannot directly convert ordinary objects, and the conversion result is empty

// Judge Set and Map types
typeof new Set(); // "object"
typeof new Map(); // "object"
Object.prototype.toString.call(new Set()); // "[object Set]"
Object.prototype.toString.call(new Map()); // "[object Map]"

4, WeakMap data structure

The Weak structure, that is, the WeakSet or WeakMap, helps prevent memory leaks

  • The WeakMap structure is similar to the Map structure and is also a collection used to generate key value pairs. However, it differs from Map as follows.
    • (1)WeakMap can only accept objects as key names (except null), and does not accept other types of values as key names. Same as WeakSet
    • (2) The object pointed to by the weakmap key name is still a weak reference and is not included in the garbage collection mechanism. Key values are not affected
    • (3)WeakMap has only four methods: WeakMap.prototype.get(value), WeakMap.prototype.set(value), WeakMap.prototype.has(value), and WeakMap.prototype.delete(value)
    • (4)WeakMap still has no way to traverse its members, that is, it has no size attribute and can't use forEach
    • (5) The application scenario of WeakMap is still that the DOM node is used as the key name. When the DOM element is cleared, the corresponding WeakMap record will be automatically removed
const map = new WeakMap();
map.set(1, 2) // TypeError: 1 is not an object!
map.set(null, 2) // TypeError: Invalid value used as weak map key

wm.set(document.getElementById('example'), 'some information'); // success

  • (4) One use of weakset is to store DOM nodes without worrying about memory leaks when these nodes are removed from the document

5, Symbol

Symbol is a new basic data type in es6, which represents a unique value. Is the seventh data type in js.

Purpose: because the attribute names of objects in es5 can only be represented by strings, it is easy to cause attribute name conflicts. Therefore, the Symbol data type is added here to represent a unique value, and then it is used as the attribute name of the object, so there will be no duplication of attribute names.

When symbol is used as the object attribute name, it cannot be traversed by the commonly used for in, Object.keys() (mention that for... of is not traversing the object, and symbol can be traversed by using for... of). Instead, use a specific Object.getOwnPropertySymbols(obj) to traverse the symbol property value (return an array containing all symbol property names)

1. Create

  • (1)Symbol() function: the value of symbol type, which is created with the Symbol() function. However, since symbol is a basic type and not an object, the new operator cannot be added.
var s1 = Symbol(),
    s2 = Symbol();
console.log(typeof s1, s1, s1 === s2,); // symbol Symbol() false
typeof Symbol(); // "symbol"
  • (2) Parameters: the function of Symbol can pass in parameters. The parameters represent the description of the Symbol and are used to distinguish each Symbol. They have no other function. If the parameter passed in is an object, call the toString method of the object first. Symbols with the same description are still not equal
var s1 = Symbol('a'),
    s2 = Symbol('a');
console.log(s1, s1 === s2); // Symbol(a) false
  • (3)Symbol as the attribute name of the object: when symbol is used as the attribute name of the object, it must be added to [], otherwise an error will occur, and the dot (.) operator cannot be used to access it.
var s1 = Symbol('s1'),
    s2 = Symbol('s2'),
    obj = {
      [s1]: 'aSymbol'
    };
obj[s2] = 'aSymbol2';
console.log(obj[s1],obj.s2); // aSymbol undefined

2. Symbol considerations

  • (1)Symbol value cannot be calculated with other types of values, otherwise an error will be reported.
var s1 = Symbol('a');
console.log(s1 + '1'); // Cannot convert a Symbol value to a string
  • (2)Symbol conversion: symbol can be converted to string and Boolean value, but not to numeric value (it will directly report an error).
var s1 = Symbol('a');
console.log(String(s1),s1.toString(),Boolean(s1)); // Symbol(a) Symbol(a) true
console.log(Number(s1)); // Cannot convert a Symbol value to a number

var s1 = Symbol('a');
if (s1) {
    console.log('show me'); // Output show me
}
  • (3)Symbol is used as the attribute name, which cannot be traversed by for... in, Object.key, etc. (mention that for... Of is not traversing the object, and symbol can be traversed by using for... Of). To get the symbol property name of an object, use the Object.getOwnPropertySymbols(obj) method to return an array containing all symbol property names of the object
var s1 = Symbol('s1'),
    s2 = Symbol('s2'),
    obj = {
      [s1]: 'aSymbol',
      [s2]: 'aSymbol2',
      normal: true
    };
for (let item in obj) {
  console.log(item); // normal
}
console.log(Object.getOwnPropertySymbols(obj)); // (2)[Symbol(s1), Symbol(s2)]

3,Symbol.for(),Symbol.keyFor()

  • Symbol.for(): it accepts a string as a parameter and is the key value of symbol. Then search whether other symbols have this key value. If so, return this symbol value. If not, create and return a symbol value with this key value.
  • The difference between Symbol.for() and Symbol(): Symbol.for() does not return a new value of symbol type every time it is called. Instead, it checks whether the given key already exists. If it does not exist, a new value will be created. Symbol () generates a new symbol value every time it is called.
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true

Symbol.keyFor(): receives a symbol value as a parameter and returns the key of the symbol value. If no key is specified, it returns undefined. keyFor is the key returned

let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

6, BigInt

  • The BigInt data type provides a way to represent integers greater than 2 ^ 53-1. BigInt can represent an integer of any size
    • Number type can only safely support integers between - (2 ^ 53-1) and 2 ^ 53-1. Any value beyond this range will lose precision
  • Create BigInt type as follows:
    • (1) Append n directly to the end of the integer
    • (2) Call the BigInt() constructor directly
    • (3) Note: BigInt can use all operators except the unary plus operator; And BigInt and Number cannot be mixed
const a = 124n;
const b = BigInt(123);
const c = BigInt(1.1); // An error is reported. BigInt must be an int first

typeof a // "bigint"
typeof b // "bigint"
console.log(b); // The output value is 123n

124n + 1; // Unexpected typeerror: cannot mix bigint and other types, use explicit conversions
+123n; // Unexpected typeerror: cannot convert a bigint value to a number at < anonymous >: 1:1
123n + 123n; // 246n
123n === 123n // true
123n + "ab" // "123ab"

Keywords: Javascript ECMAScript

Added by lastcraft on Tue, 12 Oct 2021 21:36:46 +0300