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

原生JS监听事件后修改对象属性,状态无法保留的解决方法

问题

我想在对象被使用时把它的used属性从0改成1,但写了下面的代码后,再次获取同一个对象时,used还是0:

function x() {     
    const array = [{
                    name: x,
                    surname: y,
                    used: 0
                   },{
                    name: c,
                    surname: b,
                    used:0
                   },{
                    name: f,
                    surname: g,
                    used: 0
                  }]
       
    const randomNumber = Math.floor(Math.random() * array.length)
    if (array[randomNumber].used === 0) {
                array[randomNumber] = { ..., used: 1 }; // 这里的...语法有误,需展开原对象
        }
}

哪怕对象已经进入过if判断,used值还是没变。我还试了另一种写法:

function x() {     
    const array = [{
                    name: x,
                    surname: y,
                    used: 0
                   },{
                    name: c,
                    surname: b,
                    used:0
                   },{
                    name: f,
                    surname: g,
                    used: 0
                  }]
    const randomNumber = Math.floor(Math.random() * array.length)
    if (array[randomNumber].used === 0) {
                array[randomNumber].used = 1;
        }
}

结果还是一样。请问原生JS里怎么实现类似React的state功能,让修改后的属性值能保留下来?

问题出在哪?

你代码里的array是函数x的局部变量——每次调用x(),都会重新创建一个全新的数组,之前修改的used属性根本存不住,每次调用都是从头开始,数组回到初始状态。

解决方法

1. 把数组移到函数外面(避免每次重建)

把数组放在函数外部,这样它不会随函数调用被重新创建,每次调用函数都是修改同一个数组:

// 把数组放在函数外面,作为持久化的状态
const array = [{
    name: 'x', // 注意原代码里的变量x和函数名重名了,建议改成字符串或其他变量
    surname: 'y',
    used: 0
},{
    name: 'c',
    surname: 'b',
    used:0
},{
    name: 'f',
    surname: 'g',
    used: 0
}];

function x() {     
    const randomNumber = Math.floor(Math.random() * array.length)
    if (array[randomNumber].used === 0) {
        // 直接修改属性就行,或者用展开语法做不可变更新(看需求)
        array[randomNumber].used = 1;
        // 不可变写法:array[randomNumber] = {...array[randomNumber], used: 1};
    }
}

2. 用闭包封装状态(更干净,不污染全局)

用闭包把状态藏在函数内部,只暴露操作方法,和React组件的私有state逻辑类似:

function createPicker() {
    // 这个数组只会初始化一次,被闭包保存
    const array = [{
        name: 'x',
        surname: 'y',
        used: 0
    },{
        name: 'c',
        surname: 'b',
        used:0
    },{
        name: 'f',
        surname: 'g',
        used: 0
    }];

    return function() {
        const randomIdx = Math.floor(Math.random() * array.length);
        if (array[randomIdx].used === 0) {
            array[randomIdx].used = 1;
        }
        // 返回选中的对象,方便查看结果
        return array[randomIdx];
    }
}

// 创建一个实例,每次调用这个实例都会操作同一个状态
const picker = createPicker();
picker(); // 第一次调用,修改某个对象的used为1
picker(); // 第二次调用,可能选中已修改的对象,此时used是1

3. 模拟React的useState(自定义状态管理)

如果想要更贴近React的useState体验,可以自己封装一个简单的状态函数,支持状态更新和读取:

function useState(initialState) {
    let state = initialState;
    function setState(newState) {
        // 支持传入函数计算新状态,和React一致
        state = typeof newState === 'function' ? newState(state) : newState;
    }
    // 返回获取状态的函数和更新函数
    return [() => state, setState];
}

// 使用示例
const [getArray, setArray] = useState([{
    name: 'x',
    surname: 'y',
    used: 0
},{
    name: 'c',
    surname: 'b',
    used:0
},{
    name: 'f',
    surname: 'g',
    used: 0
}]);

function x() {
    const currentArray = getArray();
    const randomIdx = Math.floor(Math.random() * currentArray.length);
    if (currentArray[randomIdx].used === 0) {
        // 不可变更新状态,和React的setState逻辑对齐
        setArray(prevArray => {
            const newArray = [...prevArray];
            newArray[randomIdx] = {...newArray[randomIdx], used: 1};
            return newArray;
        });
    }
}

内容的提问来源于stack exchange,提问作者Jure Ereš

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:10:21