我有一个目标:

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使用这个,所以我不关心跨浏览器问题。)


当前回答

最小版本

2017年

Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})
                                                  ↑↑↑↑↑

ES2019年

Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]))
                                                           ↑↑↑↑↑

其他回答

我来到这里是为了查找并回答将对象映射到数组的问题,结果得到了这个页面。如果你来这里寻找与我相同的答案,这里是如何映射和对象到一个数组。

您可以使用map从对象返回一个新数组,如下所示:

var newObject = Object.keys(myObject).map(function(key) {
   return myObject[key];
});

JavaScript刚刚获得了新的Object.fromEntries方法。

实例

函数mapObject(obj,fn){返回Object.fromEntries(对象.entries(对象).map(fn))}常量myObject={a:1,b:2,c:3}const myNewObject=mapObject(myObject,([key,value])=>([key、value*value]))console.log(myNewObject)

解释

上面的代码将Object转换为可以映射的嵌套数组([[<key>,<value>],…])。Object.fromEntries将数组转换回对象。

这种模式最酷的一点是,现在可以在映射时轻松地考虑对象关键点。

文档

对象.fromEntries()Object.entries()

浏览器支持

Object.fromEntries目前仅受这些浏览器/引擎支持,但仍有polyfill可用(例如@babel/polyfill)。

您可以在返回的键数组上使用Object.keys和forEach:

var myObject = { 'a': 1, 'b': 2, 'c': 3 },
    newObject = {};
Object.keys(myObject).forEach(function (key) {
    var value = myObject[key];
    newObject[key] = value * value;
});

或者以更模块化的方式:

function map(obj, callback) {
    var result = {};
    Object.keys(obj).forEach(function (key) {
        result[key] = callback.call(obj, obj[key], key, obj);
    });
    return result;
}

newObject = map(myObject, function(x) { return x * x; });

请注意,Object.keys返回的数组只包含对象自己的可枚举财产,因此其行为类似于for。。在循环中使用hasOwnProperty检查。

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}]}]}

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

为了获得最佳性能。

如果您的对象不经常更改,但需要经常迭代,我建议使用本地映射作为缓存。

//示例对象var obj={a:1,b:2,c:'something'};//缓存映射var objMap=新映射(Object.entries(obj));//Map对象上的快速迭代objMap.forEach((项,键)=>{//用一件物品做点什么console.log(键,项);});

Object.entries已经在Chrome、Edge、Firefox和beta Opera中运行,因此它是一个经得起未来考验的功能。这是ES7的,所以用塑料填充https://github.com/es-shims/Object.entries对于IE,它不起作用。