我尝试过寻找重复项,但总是得到 React 答案(可以理解)。
只是想知道这是否以某种方式获取和设置状态对象,以防止由于引用/改变原始状态对象而产生意外的“气味”。
抱歉,如果这看起来很简单,但我只是不确定。对更好/最佳实践非常感兴趣(如果它没有被归类为太宽泛的话)。
let state = {
name: 'Nick',
sex: 'male',
hobbies: []
}
const updateHobbies = async() => {
const hobbies = // some fetch call
setState('hobbies', hobbies);
}
const setState = (key, value) => {
state = { ...state, 'key': value }
}
const getState = () => {
return { ...state }
}
最佳答案
正如所指出的,使用经过尝试和测试的库当然是一个好主意。但有时自己动手并不是一个坏主意,特别是出于学习目的等。
下面我创建了一个带有基本深拷贝的小片段。
您会注意到浅拷贝 {...}
版本会更改 a
,但 deepCopy
不会。
如果 ES 规范实现了深层复制,那就太好了,有时人们只是这样做 -> JSON.parse(JSON.stringify(data))
这不太好,因为它会丢失大量数据类型当然,克隆对象并不简单,因为需要特别注意对象类型,例如。我的代码片段必须专门处理日期,其他对象可能也需要特别注意。但也许这可以使用与 Symbol.iterator
完成迭代相同的技术来完成..
const CloneSymbol = Symbol('clone');
Date.prototype[CloneSymbol] =
d => new Date(d.getTime());
//custom Person object with clone.
class Person {
constructor (first, last) {
this.first = first;
this.last = last;
}
get full() { return `${this.first} ${this.last}` }
}
Person.prototype[CloneSymbol] = s => {
return new Person(s.first, s.last);
}
const deepCopy = obj => {
const m = Object.entries(obj).map(
([k, v]) => {
if (v === null) return [k, v];
if (typeof v === 'object') {
const fn = v.constructor
.prototype[CloneSymbol];
return [k, fn ? fn(v) : deepCopy(v)]
} else return [k, v];
}
);
return Array.isArray(obj)
? m.reduce((a, [i, v]) => {
a[i] = v;
return a;
}, [])
: Object.fromEntries(m);
}
const a = {
nullVal: null,
seven: 7,
person: new Person('bill', 'clinton'),
date: new Date(),
one: 'one',
arr: ['hello', 'there', [1,2,3]]
}
//deep copy, b has no mutation
//a is not effect..
const b = deepCopy(a);
b.arr[0] = 'bye';
b.date.setDate(1);
b.arr[2].push(4);
console.log(b.person.full);
//shalow copy, look at a & c
const c = {...a};
c.arr[1] = 'oops';
console.log(a);
console.log(b);
console.log(c);
console.log(a.person === b.person);
关于javascript - 获取/设置状态对象(vanilla js),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74194066/