将数组转为Country对象数组后,外部无法调用对象方法问题
问题
我定义了如下Country类:
export class Country { id: number = 0 name: string = '' getNamePlusBob() { return this.name + 'bob' } }
从API获取数组数据后,我想把它转为Country类型的对象数组,于是写了hydrateArray函数:
function hydrateArray(data, entity) { let returnArray = [] console.log(data) data.forEach((row) => { const object = entity; for (const [key, value] of Object.entries(row)) { if(Object.hasOwn(object, key)) { object[key] = value } else { console.log('Key not found in entity', key) } } console.log(object.getNamePlusBob()) returnArray.push({...object}) }) return returnArray } const countries = hydrateArray(countryData, new Country())
现在遇到的问题是:在hydrateArray函数内部能正常调用object.getNamePlusBob()并得到结果,但外部调用countries[0].getNamePlusBob()时,会报错:TypeError: countries[0].getNamePlusBob is not a function。
原因分析
- 对象展开运算符丢失原型方法:你用
{...object}把entity实例的属性展开成了普通字面量对象,这个新对象仅保留了object自身的可枚举属性(id和name),但不会继承原Country类原型链上的方法(比如getNamePlusBob),所以外部调用时找不到该方法。 - 复用同一实例导致数据污染:此外还有隐藏问题——你在
forEach里直接复用传入的entity实例,每次循环都会修改同一个对象的属性,最终数组里的所有元素都是基于同一个实例展开的,会导致所有元素的属性值都是最后一次循环的结果。
解决方案
方案1:每次循环创建新的类实例
在循环中每次创建新的Country实例,而非复用传入的实例,赋值后直接push实例本身:
function hydrateArray(data, EntityClass) { let returnArray = [] data.forEach((row) => { // 每次循环生成新实例 const object = new EntityClass(); for (const [key, value] of Object.entries(row)) { if(Object.hasOwn(object, key)) { object[key] = value } else { console.log('Key not found in entity', key) } } returnArray.push(object) }) return returnArray } // 调用时传入类本身,而非实例 const countries = hydrateArray(countryData, Country)
方案2:用Object.assign保留原型链
通过Object.assign把数据赋值给新创建的实例,既保留原型链,又能批量赋值属性:
function hydrateArray(data, EntityClass) { return data.map(row => { const instance = new EntityClass(); Object.assign(instance, row); // 可选:过滤实例不存在的属性 Object.keys(row).forEach(key => { if(!Object.hasOwn(instance, key)) { console.log('Key not found in entity', key) delete instance[key]; } }) return instance; }) } const countries = hydrateArray(countryData, Country)
内容的提问来源于stack exchange,提问作者Richard Bridge
相关产品推荐
相关产品推荐

