我有一个目标:

myObject = { 'a': 1, 'b': 2, 'c': 3 }

我正在寻找一个本地方法,类似于Array.prototype.map,可按如下方式使用:

newObject = myObject.map(function (value, label) {
    return value * value;
});

// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

JavaScript是否有这样的对象映射函数?(我希望Node.JS使用这个,所以我不关心跨浏览器问题。)


当前回答

const mapObject = (targetObject, callbackFn) => {
    if (!targetObject) return targetObject;
    if (Array.isArray(targetObject)){
        return targetObject.map((v)=>mapObject(v, callbackFn))
    }
    return Object.entries(targetObject).reduce((acc,[key, value]) => {
        const res = callbackFn(key, value);
        if (!Array.isArray(res) && typeof res ==='object'){
            return {...acc, [key]: mapObject(res, callbackFn)}
        }
        if (Array.isArray(res)){
            return {...acc, [key]: res.map((v)=>mapObject(v, callbackFn))}
        }
        return {...acc, [key]: res};
    },{})
};
const mapped = mapObject(a,(key,value)=> {
    if (!Array.isArray(value) && key === 'a') return ;
    if (!Array.isArray(value) && key === 'e') return [];
    if (!Array.isArray(value) && key === 'g') return value * value;
    return value;
});
console.log(JSON.stringify(mapped)); 
// {"b":2,"c":[{"d":2,"e":[],"f":[{"g":4}]}]}

此函数递归地遍历对象和对象数组。如果返回未定义,则可以删除属性

其他回答

没有到Object对象的本机映射,但这如何:

var myObject={“a”:1,“b”:2,“c”:3};Object.keys(myObject).forEach(函数(键,索引){myObject[key]*=2;});console.log(myObject);//=>{“a”:2,“b”:4,“c”:6}

但是您可以使用for。。。在:

var myObject={“a”:1,“b”:2,“c”:3};for(myObject中的var键){if(myObject.hasOwnProperty(键)){myObject[key]*=2;}}console.log(myObject);//{“a”:2,“b”:4,“c”:6}

使现代化

很多人都提到,以前的方法不会返回新对象,而是对对象本身进行操作。为此,我想添加另一个解决方案,该方案返回一个新对象并保持原始对象的原样:

var myObject={“a”:1,“b”:2,“c”:3};//返回一个新对象,其中每个键的值都使用mapFn(value)映射函数objectMap(对象,mapFn){return Object.keys(Object).reduce(function(result,key){result[key]=mapFn(对象[key])返回结果}, {})}var newObject=对象映射(myObject,函数(值){返回值*2})console.log(newObject);//=>{“a”:2,“b”:4,“c”:6}console.log(myObject);//=>{“a”:1,“b”:2,“c”:3}

Array.prototype.reduce通过将前一个值与当前值进行某种程度的合并,将数组缩减为单个值。链由空对象{}初始化。每次迭代时,都会添加myObject的一个新键,该键的值是该键的两倍。

使现代化

有了新的ES6特性,有了一种更优雅的方式来表达objectMap。

常量对象映射=(obj,fn)=>对象.fromEntries(对象条目(obj).map(([k,v],i)=>[k,fn(v,k,i)]))常量myObject={a:1,b:2,c:3}console.log(objectMap(myObject,v=>2*v))

我的回答主要基于这里的最高评分,希望每个人都能理解(在我的GitHub上也有同样的解释)。这就是为什么他对地图的实施有效:

Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +    
')');

该函数的目的是获取一个对象,并使用对所有对象(对象和数组都一样)可用的方法修改对象的原始内容,而不返回数组。JS中的几乎所有东西都是一个对象,因此,继承管道下游的元素在技术上可能会使用上游元素可用的对象(反之亦然)。

这之所以有效,是因为.map函数返回了一个数组REQUIRING,您可以提供一个数组的显式或隐式RETURN,而不是简单地修改现有对象。你本质上通过使用object.keys来欺骗程序,使其认为对象是一个数组,这将允许你使用map函数,并将其作用于各个键关联的值(我实际上意外返回了数组,但已修复)。只要没有正常意义上的返回,就不会创建原始对象仍然完整并按程序修改的数组。

这个特定的程序获取一个名为images的对象,并获取其键的值,并附加url标记以供在另一个函数中使用。原文如下:

var images = { 
snow: 'https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305', 
sunny: 'http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-east-   
Matanzas-city- Cuba-20170131-1080.jpg', 
rain: 'https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg' };

…并修改为:

var images = { 
snow: url('https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305'),     
sunny: url('http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-   
east-Matanzas-city- Cuba-20170131-1080.jpg'), 
rain: url('https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg') 
};

对象的原始结构保持不变,只要没有返回,就可以正常访问属性。不要让它像正常一样返回数组,一切都会好起来。目标是将原始值(图像[key])重新设计为所需的值,而不是其他值。据我所知,为了防止数组输出,必须有图像的重新分配[key],并且没有返回数组的隐式或显式请求(变量赋值完成了这一点,并且对我来说来回出现问题)。

编辑:

要解决他关于创建新对象的另一个方法,以避免修改原始对象(为了避免意外创建数组作为输出,似乎仍然需要重新分配)。这些函数使用箭头语法,如果您只是想创建一个新对象以供将来使用,则可以使用。

const mapper = (obj, mapFn) => Object.keys(obj).reduce((result, key) => {
                result[key] = mapFn(obj)[key];
                return result;
            }, {});

var newImages = mapper(images, (value) => value);

这些功能的工作方式如下:

mapFn接受稍后要添加的函数(在这种情况下(value)=>value),并简单地返回存储在那里的任何内容,

然后在result[key]=mapFn(obj)[key]中重新定义与键关联的原始值

并返回对结果执行的操作(位于括号中的累加器在reduce函数结束时启动)。

所有这些都是在所选对象上执行的,但仍然不能对返回的数组进行隐式请求,只有在我所知的重新分配值时才有效。这需要一些心理体操,但减少了所需的代码行,如上文所示。输出完全相同,如下所示:

{snow: "https://www.trbimg.com/img-5aa059f5/turbine/bs-   
md-weather-20180305", sunny: "http://www.cubaweather.org/images/weather-
photos/l…morning-east-Matanzas-city-Cuba-20170131-1080.jpg", rain: 
"https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg"}

请记住,这适用于非数字。通过在mapFN函数中简单地返回值,可以复制任何对象。

Hey编写了一个可能有帮助的小映射器函数。

    function propertyMapper(object, src){
         for (var property in object) {   
           for (var sourceProp in src) {
               if(property === sourceProp){
                 if(Object.prototype.toString.call( property ) === '[object Array]'){
                   propertyMapper(object[property], src[sourceProp]);
                   }else{
                   object[property] = src[sourceProp];
                }
              }
            }
         }
      }

我需要一个允许修改密钥的版本(基于@Amberlamps和@yonatanmn答案);

var facts = [ // can be an object or array - see jsfiddle below
    {uuid:"asdfasdf",color:"red"},
    {uuid:"sdfgsdfg",color:"green"},
    {uuid:"dfghdfgh",color:"blue"}
];

var factObject = mapObject({}, facts, function(key, item) {
    return [item.uuid, {test:item.color, oldKey:key}];
});

function mapObject(empty, obj, mapFunc){
    return Object.keys(obj).reduce(function(newObj, key) {
        var kvPair = mapFunc(key, obj[key]);
        newObj[kvPair[0]] = kvPair[1];
        return newObj;
    }, empty);
}

factObject(事实对象)=

{
"asdfasdf": {"color":"red","oldKey":"0"},
"sdfgsdfg": {"color":"green","oldKey":"1"},
"dfghdfgh": {"color":"blue","oldKey":"2"}
}

编辑:对传入起始对象{}进行轻微更改。允许为[](如果键是整数)

这是另一个版本,它允许映射函数根据当前键和值声明任意数量的新财产(键和值)。E: 现在也可以使用数组。

Object.defineProperty(Object.prototype,“mapEntries”{value:函数(f,a=Array.isArray(this)?[]:{}) {return Object.entries(this).reduce((o,[k,v])=>对象赋值(o,f(v,Array.isArray(a)?数字(k):k,this)),a) ;}});常量数据={a:1,b:2,c:3};常量计算=(v,k)=>({[k+'_square']:v*v,[k+'_cube']:v*v*v});console.log(data.mapEntries(计算));// {//“a_square”:1,“a_scube”:1,//“b_square”:4,“b_cube”:8,//“c_square”:9,“c_cube”:27// }//阵列演示:常量arr=[“a”、“b”、“c”];常量重复=(v,i)=>({[i*2]:v,[i*2+1]:v+v});console.log(arr.mapEntries(重复));//[“a”、“aa”、“b”、“bb”、“c”、“cc”]