You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让对象/数组重赋值的变更在多类间可见以实现指针式行为

JavaScript中实现引用类型重赋值后的跨实例同步

原代码示例

class ClassA {
    constructor(positon, obj) {
        this.position = positon
        this.obj = obj
    }
}
    
class ClassB {
    constructor() {
        this.position = [1, 2]
        this.obj = {
            pos: [1, 2, 3],
            rot: [4, 5, 6]
        }
        this.classAInstance = new ClassA(this.position , this.obj)
    }
}

class ClassC {
    constructor(position, obj) {
        this.obj = obj
        this.position = position
    }

    reassignObj(){
        this.obj = {
            pos: [4, 5, 6],
            rot: [7, 8, 9]
        }
    }

    resetObj() {
        this.obj.pos = [4, 5, 6],
        this.obj.rot = [7, 8, 9]
    }

    reassignPosition() {
        this.position = [3, 4]
    }

    resetPosition() {
        this.position[0] = 3
        this.position[1] = 4
    }
}
        
let fItem = new ClassB()
let other = new ClassC(fItem.position, fItem.obj)
other.resetObj()
other.resetPosition()
console.log('RE-SETTING')
console.log('FITEM', fItem.position, fItem.obj)
console.log('OTHER', other.position, other.obj)
fItem = new ClassB()
other = new ClassC(fItem.position, fItem.obj)
other.reassignObj()
other.reassignPosition()
console.log('RE-ASSINGNING')
console.log('FITEM', fItem.position, fItem.obj)
console.log('OTHER', other.position, other.obj)

运行输出

//RESETTING
FITEM [ 3, 4 ] { pos: [ 4, 5, 6 ], rot: [ 7, 8, 9 ] }
OTHER [ 3, 4 ] { pos: [ 4, 5, 6 ], rot: [ 7, 8, 9 ] } // changes visible to other
//REASSIGNING
FITEM [ 1, 2 ] { pos: [ 1, 2, 3 ], rot: [ 4, 5, 6 ] }
OTHER [ 3, 4 ] { pos: [ 4, 5, 6 ], rot: [ 7, 8, 9 ] } // changes not visible to other

问题核心

修改引用类型的内部属性时,所有持有该引用的实例都能同步看到变化;但直接重赋值整个对象/数组时,会让当前实例的引用指向新对象,原引用的实例无法感知到变化。要实现类似指针的跨实例同步,核心是保持共享的顶层引用不变,只修改其内部内容。


解决方案

1. 使用外层容器对象

把需要共享的数组/对象包装到一个外层容器中,所有实例引用这个容器。重赋值时,修改容器的属性而非替换容器本身,这样所有实例的容器引用不变,自然能同步看到新值。

修改后的代码示例:

class ClassA {
    constructor(positon, obj) {
        this.position = positon
        this.obj = obj
    }
}
    
class ClassB {
    constructor() {
        // 用容器包装需要共享的属性
        this.sharedContainer = {
            position: [1, 2],
            obj: {
                pos: [1, 2, 3],
                rot: [4, 5, 6]
            }
        }
        this.classAInstance = new ClassA(
            this.sharedContainer.position, 
            this.sharedContainer.obj
        )
    }
}

class ClassC {
    constructor(sharedContainer) {
        this.sharedContainer = sharedContainer
    }

    reassignObj(){
        // 修改容器的obj属性,而非替换当前实例的obj引用
        this.sharedContainer.obj = {
            pos: [4, 5, 6],
            rot: [7, 8, 9]
        }
    }

    reassignPosition() {
        // 修改容器的position属性,而非替换当前实例的position引用
        this.sharedContainer.position = [3, 4]
    }
}
        
let fItem = new ClassB()
let other = new ClassC(fItem.sharedContainer)
other.reassignObj()
other.reassignPosition()
console.log('RE-ASSINGNING WITH CONTAINER')
console.log('FITEM', fItem.sharedContainer.position, fItem.sharedContainer.obj)
console.log('OTHER', other.sharedContainer.position, other.sharedContainer.obj)

运行输出:

RE-ASSINGNING WITH CONTAINER
FITEM [ 3, 4 ] { pos: [ 4, 5, 6 ], rot: [ 7, 8, 9 ] }
OTHER [ 3, 4 ] { pos: [ 4, 5, 6 ], rot: [ 7, 8, 9 ] }

2. 集中式共享状态

创建一个全局或单例的共享状态对象,所有实例直接引用这个状态对象的属性。修改时直接操作状态对象的属性,所有实例都会同步感知到变化。

代码示例:

// 全局共享状态
const GlobalSharedState = {
    position: [1, 2],
    obj: {
        pos: [1, 2, 3],
        rot: [4, 5, 6]
    }
}

class ClassA {
    constructor() {
        this.position = GlobalSharedState.position
        this.obj = GlobalSharedState.obj
    }
}
    
class ClassB {
    constructor() {
        this.classAInstance = new ClassA()
    }
}

class ClassC {
    reassignObj(){
        GlobalSharedState.obj = {
            pos: [4, 5, 6],
            rot: [7, 8, 9]
        }
    }

    reassignPosition() {
        GlobalSharedState.position = [3, 4]
    }
}
        
let fItem = new ClassB()
let other = new ClassC()
other.reassignObj()
other.reassignPosition()
console.log('RE-ASSINGNING WITH GLOBAL STATE')
console.log('FITEM', fItem.classAInstance.position, fItem.classAInstance.obj)
console.log('OTHER', GlobalSharedState.position, GlobalSharedState.obj)

3. 使用Proxy拦截赋值(进阶)

通过Proxy创建一个代理对象,拦截赋值操作,自动将新值同步到共享的目标引用上。这种方式更灵活,适合需要监听变化的场景。

代码示例:

function createSharedProxy(target) {
    return new Proxy(target, {
        set(target, prop, value) {
            // 直接修改原始目标的属性
            target[prop] = value
            return true
        }
    })
}

class ClassB {
    constructor() {
        this.shared = {
            position: [1, 2],
            obj: {
                pos: [1, 2, 3],
                rot: [4, 5, 6]
            }
        }
        this.classAInstance = new ClassA(
            createSharedProxy(this.shared.position),
            createSharedProxy(this.shared.obj)
        )
    }
}

class ClassC {
    constructor(shared) {
        this.position = createSharedProxy(shared.position)
        this.obj = createSharedProxy(shared.obj)
    }

    reassignObj(){
        // 赋值操作会被Proxy拦截,同步修改原始shared.obj
        Object.assign(this.obj, { pos: [4,5,6], rot: [7,8,9] })
    }

    reassignPosition() {
        // 直接修改数组元素,或用Object.assign替换数组(数组是特殊对象)
        Object.assign(this.position, [3,4])
    }
}

内容的提问来源于stack exchange,提问作者rustyBucketBay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:45:20