JS中传入子函数的引用类型参数在父函数被意外修改问题咨询
问题原因
JavaScript的变量传递遵循以下规则:
- 基础类型(数字、字符串、布尔值、null、undefined、Symbol)为值传递,函数内部修改参数不会影响外部原值
- 引用类型(对象、数组、函数等)传递的是内存地址的拷贝,函数内部拿到的参数和外部原变量指向同一块内存空间,只要直接修改该地址指向的实体内容,就会同步影响外部的原变量,和变量是否为全局变量没有关联。
你的代码中state是二维数组,属于引用类型,transitionState函数里直接对state[individual.pairIndex][individual.index]做赋值修改,本质是直接修改了原内存地址里的内容,因此外部的state会被同步修改。
解决方法
要避免原对象被修改,核心是做深拷贝,在修改前先创建一个和原内容完全一致、但内存地址独立的新对象,所有修改都在新对象上进行:
方法1:针对二维数组场景分层拷贝
你的state是两层数组,可在validateTransition中先对state做分层拷贝,后续所有校验逻辑都基于拷贝后的对象操作:
function validateTransition(boatShore, boat, state) { // 先拷贝state,所有修改都在拷贝后的对象上做 const copiedState = state.map(item => [...item]) if (boat.length > 2 || boat.length < 1) { return false } for (let individual of boat) { if (boatShore !== copiedState[individual.pairIndex][individual.index]) return false; } const newState = transitionState(boat, copiedState) for (let pair of newState) { if (pair[0] !== pair[1]) { for (let pairCheck of newState) { if (pairCheck[0] === pair[1]) { return false; } } } } return true; }
方法2:通用深拷贝方案
如果数据结构更复杂,可以用structuredClone全局方法做深拷贝,简单场景也可用JSON序列化反序列化的方式(仅支持处理JSON兼容的普通数据类型,不可处理函数、Symbol、循环引用等场景):
// structuredClone方案,兼容现代浏览器和Node.js 17+版本 const copiedState = structuredClone(state) // 序列化方案,简单场景可直接使用 const copiedState = JSON.parse(JSON.stringify(state))
内容的提问来源于stack exchange,提问作者Ionut Eugen
相关产品推荐
相关产品推荐

