In-depth Understanding of ES6 007 [Study Notes]

Set and Map Collections. In JS, there is an `in` operator that can determine if a property exists in an object without needing to read the object's value, returning true if it exists. However, the `in` operator also checks the object's prototype chain, so using this method is only relatively safe when the object's prototype is null. Set Collection: `let set = new Set()` `set.add(5)` `set.add("5")` `console.log(s…`

Set Collection and Map Collection

In JS, there is an in operator, which can determine if a property exists in an object without needing to read the object's value; if it exists, it returns true. However, the `in` operator also checks the object's prototype, so this method is only reliable when the object's prototype is null.

Set Collection

let set = new Set()
set.add(5)
set.add("5")
console.log(set.size) // 2
const key1={},key2={}
set.add(key1)
set.add(key1)
console.log(set.size) // 4
// 传入相同值实际上会被忽略
let set1 = new Set(1,2,3,4,5,5,5,5)
console.log(set.size) //5
set1.has(5) //true
set1.has(6) // false
set1.delete(5)
set1.has(5) //false

set1.clear() // 所有元素被清除

A Set collection does not perform forced type conversion on stored values; the number 5 and the string "5" can exist as two independent elements (the engine uses `Object.is()` as mentioned before for judgment). If multiple objects are added to a Set, they remain independent of each other.

Set Collection's forEach Method

The callback function of the forEach() method accepts the following 3 parameters

  • The next index position in the Set collection
  • A value identical to the first parameter
  • The Set collection being iterated over itself

The `forEach()` method of a Set collection has a peculiar difference from the `forEach()` method in arrays: the values of the first two parameters of the callback function are actually the same. In fact, the `forEach()` callback function of a Map collection also accepts 3 parameters, where the first two are the value and the key, respectively.

The second parameter of the `forEach` function is the same as for arrays; if `this` needs to be used within the callback function, it can be passed as the second argument.

let set = new Set([1,2])
let processor = {
  output(value){
    console.log(value)
  },
  process(dataSet){
    // 这里使用箭头函数,就无须再将this作为第二个参数传入回调函数了
    dataSet.forEach(function(value){
      this.output(value)
    },this)
  }
}
processor.process(set)

Although Set collections are more suitable for tracking multiple values and each element in the collection can be manipulated using the `forEach()` method, you cannot access elements in a collection directly by index like you would with array elements. If necessary, it's best to convert the Set collection into an array first.

let set = new Set([1,2,3,3,3,4,5])
arrray = [...set]
console.log(array) // [1,2,3,4,5] 去重

function eliminateDuplicates(items){
  return [...new Set(items)]
}
let numbers = [1,2,3,3,3,4,5],
noDuplicates = eliminateDuplicates(numbers);
console.log(noDuplicates); // [1,2,3,4,5]

Weak Set Collection

Storing an object in a Set instance is similar to storing it in a variable: as long as a reference exists in the Set instance, the garbage collector cannot free the object's memory space. Thus, the Set type mentioned earlier can be considered a Set collection with strong references. As follows:

let set = new Set(),
key = {};
set.add(key);
console.log(set.size) // 1
// 移除原始引用
key = null;
console.log(set.size) // 1
// 重新取回原始引用
key = [...set][0]

For example, if we use this Set to store a DOM object, and a script removes this DOM element, the Set will still retain this reference (causing a memory leak). Therefore, ES6 introduced the WeakSet collection. A WeakSet can only store weak references to objects and cannot store primitive values; if a weak reference in the collection is the object's only reference, it will be garbage collected and its memory released.

// 集合支持add()/has()/delete()
let set = new WeakSet(),key = {};
// 向集合添加对象
set.add(key);
console.log(set.has(key)); // true
set.delete(key);
console.log(set.has(key)); // false
let key1 = {}, key2 = {};
set = new WeakSet([key1,key2]) // 如果数组中包含其非对象值,程序会抛出错误
console.log(set.has(key1)) // true
console.log(set.has(key2)) // true

// #################
// 移除对象key的最后一个强引用(Weak Set中的引用也自动移除)
let set = new Set(),
key = {};
set.add(key);
console.log(set.has(key)) // true
// 移除对象key的最后个强引用(Weak Set中的引用也自动移除)
key = null;
// 这段代码执行过后,就无法访问WeakSet中的key的引用了,由于我们需要向has方法传递一个强引用才能验证这个弱引用是否已被移除了。
  • WeakSet
  • Passing non-object arguments to the add/has/delete methods will cause the program to throw an error.
  • Not iterable; cannot use `for-of` loops.
  • Does not expose any iterators (`keys` and `values`), so its contents cannot be inspected by the program itself.
  • Does not support `forEach`.
  • Does not support `size`.

Map

  • set
  • get
  • has
  • delete
  • clear
  • size property

Initialization Method

let map = new Map([["name","Nicholas"],["age",23]])

forEach((value,key,ownerMap)=>{}, binding context)

let map = new Map([["name","Nicholas"],["age",23]])
map.forEach(function(value,key,ownerMap){
   console.log(key+" "+value);
   console.log(ownerMap === map)
})

WeakMap

The principle is consistent with WeakSet: keys are weak references to objects, and keys can only store objects.

let map = new WeakMap(),
element = document.querySelector('.element');
map.set(element,"Original")
let value = map.get(element)
console.log(value) // Original
// 移除element元素
element.parentNode.removeChild(element);
element = null;
// 此时Weak Map集合为空

Private Object Data

function Person(name){
  this._name = name;
}
Person.prototype.getName = function(){
  return this._name;
}
// 约定前缀为下划线的属性为私有属性,不允许在对象实例外改变这个属性。例如,只能通过getName()方法读取this._name,所以它也有可能在无意间被覆写

ES5 can create an object with nearly true private data using the following pattern:

var Person = (function(){
  var privateData = {},
  privateId = 0;
  function Person(name){
    Object.defineProperty(this,"_id",{value:privateId++})
    privateData[this._id] = {
      name:name
    }
  }
  Person.prototype.getName = function(){
    return privateData[this._id].name
  }
  return Person
}())

When the `Person` constructor is called, the value of the `_id` property is incremented by 1. This property is non-enumerable, non-configurable, and non-writable. The biggest problem with the above code is the inability to actively manage it; since it's impossible to know when an object instance is destroyed, the data in `privateData` will never disappear. However, using a WeakMap collection can solve this problem.

let Person = (function(){
  let privateData = new WeakMap();
  function Person(name){
    privateData.set(this,{name:name})
  }
  Person.prototype.getName = function(){
    return privateData.get(this).name
  }
  return Person
}())
// 只要对象实例被销毁,相关信息也会被销毁,从而保证了信息的私有性

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://www.walker-learn.xyz/archives/4333

(0)
Walker的头像Walker
上一篇 Mar 8, 2025 12:51
下一篇 Mar 8, 2025 12:51

Related Posts

  • Node: In-depth Yet Easy to Understand (Shengsi Garden Education) 003 [Study Notes]

    WebSocket and SSE Overview WebSocket Basics Definition: WebSocket is a full-duplex connection upgraded after an HTTP handshake, allowing clients and servers to push data bidirectionally over the same TCP channel, eliminating the need for repeated polling. Handshake Process: The client initiates an HTTP request with the Upgrade: websocket header; The server responds with 101 Switching Protocols, and both parties agree...

    Personal Nov 24, 2025
    41700
  • In-depth Understanding of ES6 001 [Study Notes]

    Block-Level Scope Binding
    Previously, `var` variable declarations, regardless of where they were declared, were considered to be declared at the top of their scope. Since functions are first-class citizens, the typical order was `function functionName()`, followed by `var variable`.

    Block-Level Declarations
    Block-level declarations are used to declare variables that cannot be accessed outside the scope of a specified block. Block-level scope exists in:
    - Inside functions
    - Within blocks (the region between `{` and `}`)

    Temporal Dead Zone
    When the JavaScript engine scans code and finds variable declarations, it either hoists them to the top of the scope...

    Personal Mar 8, 2025
    1.8K00
  • [Opening]

    I am Walker, born in the early 1980s, a journeyer through code and life. A full-stack development engineer, I navigate the boundaries between front-end and back-end, dedicated to the intersection of technology and art. Code is the language with which I weave dreams; projects are the canvas on which I paint the future. Amidst the rhythmic tapping of the keyboard, I explore the endless possibilities of technology, allowing inspiration to bloom eternally within the code. An avid coffee enthusiast, I am captivated by the poetry and ritual of every pour-over. In the rich aroma and subtle bitterness of coffee, I find focus and inspiration, mirroring my pursuit of excellence and balance in the world of development. Cycling...

    Feb 6, 2025 Personal
    2.4K00
  • In-depth Understanding of ES6 003 [Study Notes]

    Function parameter default values, as well as some details about the `arguments` object, how to use expressions as parameters, and the temporal dead zone for parameters. Previously, setting default values always relied on expressions containing the logical OR operator. When the preceding value was false, the latter value would always be returned. However, this became problematic if we passed 0 as an argument, requiring type verification. For example, `function makeRequest(url,timeout,callback){ timeout = t...`

    Personal Mar 8, 2025
    1.3K00
  • In-depth Understanding of ES6 008 [Study Notes]

    Iterators (Iterator) and Generators (Generator) are new features indispensable for efficient data processing. You will also find iterators present in other language features: the new for-of loop, the spread operator (...), and even asynchronous programming can use iterators. An iterator is a special object that has proprietary interfaces specifically designed for the iteration process. All iterator objects have a next() method, and each call returns a result pair...

    Personal Mar 8, 2025
    1.2K00
EN
简体中文 繁體中文 English