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

将数组转为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:55:21