26 内存管理(Managing Memory)

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]] 内部槽。
Normative Optional

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,那么该 target 值在当前这次 ECMAScript 代码执行完成之前不应被垃圾回收。AddToKeptObjects 操作用于确保读取一致性。

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

// ... 稍后 ...

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

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

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "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. fn 为活动函数对象
  5. finalizationRegistry.[[Realm]] 设为 fn.[[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% 属性的初始值是字符串 "FinalizationRegistry"

该属性的特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.2.4 FinalizationRegistry 实例的属性

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