26 内存管理

26.1 WeakRef 对象

WeakRef 是一种对象,用于在不阻止目标对象或 symbol 被垃圾回收的情况下引用它。WeakRef 可以被解引用,以便在目标尚未被垃圾回收回收时访问目标值。

26.1.1 WeakRef 构造器

WeakRef 构造器:

  • %WeakRef%
  • 全局对象"WeakRef" 属性的初始值。
  • 在作为构造器调用时创建并初始化一个新的 WeakRef。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。打算继承指定 WeakRef 行为的子类构造函数,必须包含一次对 WeakRef 构造函数super 调用,以创建并初始化子类实例,使其具备支持 WeakRef.prototype 的内置方法所必需的内部状态。

26.1.1.1 WeakRef ( target )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  3. weakRef 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »)。
  4. 执行 AddToKeptObjects(target)。
  5. weakRef.[[WeakRefTarget]] 设置为 target
  6. 返回 weakRef

26.1.2 WeakRef 构造器的属性

WeakRef 构造器:

26.1.2.1 WeakRef.prototype

WeakRef.prototype 的初始值是 WeakRef 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.1.3 WeakRef 原型对象的属性

WeakRef 原型对象

  • %WeakRef.prototype%
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 普通对象
  • 没有 [[WeakRefTarget]] 内部槽。

26.1.3.1 WeakRef.prototype.constructor

WeakRef.prototype.constructor 的初始值是 %WeakRef%

26.1.3.2 WeakRef.prototype.deref ( )

此方法在被调用时执行以下步骤:

  1. weakRefthis 值。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。
Note

如果 WeakRef 返回的 target 值不是 undefined,则在 ECMAScript 代码的当前执行完成之前,不应对该 target 值进行垃圾回收。AddToKeptObjects 操作确保读取一致性得以维持。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... later ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

在上面的示例中,如果第一次 deref 求值结果不是 undefined,则第二次 deref 也不可能是 undefined

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakRef"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.4 WeakRef 抽象操作

26.1.4.1 WeakRefDeref ( weakRef )

The abstract operation WeakRefDeref takes argument weakRef (a WeakRef) and returns an ECMAScript language value. It performs the following steps when called:

  1. targetweakRef.[[WeakRefTarget]]
  2. 如果 target 不是 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target
  3. 返回 undefined
Note

抽象操作与 WeakRef.prototype.deref 分开定义,严格来说是为了能够简洁地定义活性。

26.1.5 WeakRef 实例的属性

WeakRef 实例是普通对象,继承自 WeakRef 原型对象的属性。WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是一种对象,用于管理在目标对象和 symbol 被垃圾回收时执行的清理操作的注册和注销。

26.2.1 FinalizationRegistry 构造器

FinalizationRegistry 构造器:

  • %FinalizationRegistry%
  • 全局对象"FinalizationRegistry" 属性的初始值。
  • 在作为构造器调用时创建并初始化一个新的 FinalizationRegistry。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。打算继承指定 FinalizationRegistry 行为的子类构造函数,必须包含一次对 FinalizationRegistry 构造函数super 调用,以创建并初始化子类实例,使其具备支持 FinalizationRegistry.prototype 的内置方法所必需的内部状态。

26.2.1.1 FinalizationRegistry ( cleanupCallback )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,则抛出一个 TypeError 异常。
  2. 如果 IsCallable(cleanupCallback) 为 false,则抛出一个 TypeError 异常。
  3. finalizationRegistry 为 ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »)。
  4. activeFunc活动函数对象
  5. finalizationRegistry.[[Realm]] 设为 activeFunc.[[Realm]]
  6. finalizationRegistry.[[CleanupCallback]] 设为 HostMakeJobCallback(cleanupCallback)。
  7. finalizationRegistry.[[Cells]] 设为一个新的空 List
  8. 返回 finalizationRegistry

26.2.2 FinalizationRegistry 构造器的属性

FinalizationRegistry 构造器:

26.2.2.1 FinalizationRegistry.prototype

FinalizationRegistry.prototype 的初始值是 FinalizationRegistry 原型对象

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.2.3 FinalizationRegistry 原型对象的属性

FinalizationRegistry 原型对象

  • %FinalizationRegistry.prototype%
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 普通对象
  • 没有 [[Cells]][[CleanupCallback]] 内部槽。

26.2.3.1 FinalizationRegistry.prototype.constructor

FinalizationRegistry.prototype.constructor 的初始值是 %FinalizationRegistry%

26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )

此方法在被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  4. 如果 SameValue(target, heldValue) 是 true,则抛出 TypeError 异常。
  5. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则
    1. 如果 unregisterToken 不是 undefined,则抛出 TypeError 异常。
    2. unregisterToken 设置为 empty
  6. cellRecord { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. cell 追加到 finalizationRegistry.[[Cells]]
  8. 返回 undefined
Note

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]] 是活的;不过,这并不一定意味着 cell.[[UnregisterToken]]cell.[[Target]] 是活的。例如,以对象自身作为 unregister token 注册该对象,并不会使该对象永远保持存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

此方法在被调用时执行以下步骤:

  1. finalizationRegistrythis 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则抛出 TypeError 异常。
  4. removedfalse
  5. finalizationRegistry.[[Cells]] 的每个 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell,执行:
    1. 如果 cell.[[UnregisterToken]] 不是 emptySameValue(cell.[[UnregisterToken]], unregisterToken) 是 true,则
      1. finalizationRegistry.[[Cells]] 中移除 cell
      2. removed 设置为 true
  6. 返回 removed

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "FinalizationRegistry"

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.2.4 FinalizationRegistry 实例的属性

FinalizationRegistry 实例是普通对象,继承自 FinalizationRegistry 原型对象的属性。FinalizationRegistry 实例还具有 [[Cells]][[CleanupCallback]] 内部槽。