类
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
纯对象(无原型的对象)、数组、Map 和 Set 始终会被 Immer 草稿化。其他所有对象必须使用 immerable 符号标记自身与 Immer 兼容。当这些对象在生产者函数中被修改时,其原型会在副本间保留。
import {immerable} from "immer"
class Foo {
[immerable] = true // Option 1
constructor() {
this[immerable] = true // Option 2
}
}
Foo[immerable] = true // Option 3
示例
import {immerable, produce} from "immer"
class Clock {
[immerable] = true
constructor(hour, minute) {
this.hour = hour
this.minute = minute
}
get time() {
return `${this.hour}:${this.minute}`
}
tick() {
return produce(this, draft => {
draft.minute++
})
}
}
const clock1 = new Clock(12, 10)
const clock2 = clock1.tick()
console.log(clock1.time) // 12:10
console.log(clock2.time) // 12:11
console.log(clock2 instanceof Clock) // true
详细语义
类对象的草稿化语义如下:
类的草稿是一个新对象,但保留与原始对象相同的原型。
创建草稿时,Immer 会将所有自有属性从基对象复制到草稿(严格模式下包含不可枚举属性和符号属性)。
自有 getter 会在复制过程中被调用,行为与
Object.assign一致。继承的 getter 和方法将保持不变并由草稿继承,因为它们存储在未被修改的原型上。
Immer 不会调用构造函数。
最终实例的创建机制与草稿创建机制相同。
仅当 getter 同时具有 setter 时,该属性在草稿中才可写,否则无法回写值。
由于 Immer 会将对象的自有 getter 解引用为普通属性,因此可以处理在字段上使用 getter/setter 陷阱的对象(如 MobX 和 Vue 的响应式对象)。
注意:出于性能考虑,默认情况下 Immer 不严格处理对象的不可枚举属性(如 getter/setter)。如需严格处理,可通过 useStrictShallowCopy(config) 启用。使用 true 始终严格复制,或 "class_only" 仅对类实例严格复制(普通对象仍使用更快的宽松复制)。默认值为 false。(请记住:无论严格模式如何,自有 getter/setter 始终按值复制。目前没有按描述符原样复制的配置选项,欢迎提交功能需求或 PR)。
Immer 不支持原生特殊对象(如 DOM 节点或 Buffer),也不支持 Map/Set/数组的子类化,且 immerable 符号不能用于这些对象。
因此,处理如 Date 对象时,应始终创建新的 Date 实例而非修改现有 Date 实例。