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

如何通过Array.reduce()的reducer函数复制对象原型并保留大写键

解决方案

核心问题分析

你当前的代码中,reduce的初始值是普通空对象{},它的原型是Object.prototype,因此无法继承原feature对象的原型链。而直接使用Object.setPrototypeOf(accumulator, item)会让新对象的原型指向原item本身,导致原item的自身属性(包括小写键)通过原型链被访问到,最终出现大小写属性并存的问题。

优化实现方式

我们可以直接创建继承原对象原型的空对象作为初始值,再手动添加处理后的属性,这样既能保留原型链,又不会引入原对象的自身属性。

写法一(基于原reduce逻辑修改)

function doCapitalizeFeatureKeys(in_obj){
    if(in_obj.features && in_obj.features.length > 0){
        const obj2 = in_obj.features.map(item => {
            // 获取原item的原型,创建继承该原型的空对象作为accumulator初始值
            const itemProto = Object.getPrototypeOf(item);
            return Object.keys(item).reduce((accumulator, currentValue) => {
                if(currentValue === "attributes" && item[currentValue]){
                    // 可选:让attributes对象也继承原attributes的原型
                    const attrProto = Object.getPrototypeOf(item[currentValue]);
                    const cap = Object.keys(item[currentValue]).reduce((acc, curr) => {
                        acc[curr.toUpperCase()] = item[currentValue][curr];
                        return acc;
                    }, Object.create(attrProto));
                    accumulator[currentValue] = cap;
                } else {
                    accumulator[currentValue] = item[currentValue];
                }
                return accumulator;
            }, Object.create(itemProto));
        });
        in_obj.features = obj2;
        return in_obj;
    }
    return in_obj;
}

写法二(更简洁的版本)

使用Object.fromEntries替代嵌套reduce,代码可读性更强:

function doCapitalizeFeatureKeys(in_obj){
    // 提前判断,简化逻辑
    if(!in_obj.features?.length) return in_obj;

    in_obj.features = in_obj.features.map(item => {
        // 创建继承原item原型的新对象
        const newFeature = Object.create(Object.getPrototypeOf(item));
        
        // 遍历原item的所有自身属性
        for(const key of Object.keys(item)){
            if(key === "attributes" && item[key]){
                // 将attributes的键转大写,同时可选继承原attributes的原型
                const attrProto = Object.getPrototypeOf(item[key]);
                newFeature[key] = Object.assign(
                    Object.create(attrProto),
                    Object.fromEntries(
                        Object.entries(item[key]).map(([k, v]) => [k.toUpperCase(), v])
                    )
                );
            } else {
                // 其他属性直接赋值
                newFeature[key] = item[key];
            }
        }
        return newFeature;
    });

    return in_obj;
}

关键说明

  1. 原型继承:通过Object.create(Object.getPrototypeOf(item))创建的新对象,直接继承原item的原型链,不会包含原item的自身属性。
  2. 属性控制:我们只手动添加需要保留的属性(处理后的attributes和其他原样属性),因此新对象不会出现原小写属性的残留。
  3. 可选扩展:如果不需要attributes对象继承原型,可以去掉Object.create(attrProto)相关代码,直接使用Object.fromEntries的结果即可。

内容的提问来源于stack exchange,提问作者M Alok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:07:08