我有一个目标:

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


当前回答

只需使用以下命令,即可将对象转换为数组:

可以将对象值转换为数组:

myObject={“a”:1,“b”:2,“c”:3};let valuesArray=Object.values(myObject);console.log(valuesArray);

可以将对象关键帧转换为数组:

myObject={“a”:1,“b”:2,“c”:3};let keysArray=Object.keys(myObject);console.log(keyArray);

现在您可以执行正常的数组操作,包括“map”函数

其他回答

公认的答案有两个缺点:

它误用了Array.prototype.reduce,因为reduce意味着改变复合类型的结构,这在这种情况下不会发生。它不是特别可重复使用


ES6/ES2015功能方法

请注意,所有函数都是以货币形式定义的。

//小型、可重复使用的辅助功能constkeys=o=>对象.keys(o);constassign=(…o)=>对象.assign({},…o);const-map=f=>xs=>xs.map(x=>f(x));常量mul=y=>x=>x*y;常量sqr=x=>mul(x)(x);//实际地图功能常量omap=f=>o=>{o=分配(o);//A.映射(x=>o[x]=f(o[x]))(键(o));//B返回o;};//模拟数据常量o={“a”:1,“b”:2,“c”:3};//并运行控制台日志(omap(sqr)(o));控制台日志(omap(mul(10))(o));

在线A o被重新分配。由于Javascript通过共享传递引用值,因此生成了o的浅拷贝。我们现在能够在omap中突变o,而不在父作用域中突变o。在B行中,map的返回值被忽略,因为map执行了o的变异。由于此副作用仍在omap中,并且在父范围中不可见,因此完全可以接受。

这不是最快的解决方案,而是一个声明性和可重用的解决方案。以下是与单行相同的实现,简洁但可读性较差:

const omap = f => o => (o = assign(o), map(x => o[x] = f(o[x])) (keys(o)), o);

附录-为什么默认情况下对象不可迭代?

ES2015指定了迭代器和可迭代协议。但对象仍然不可迭代,因此不可映射。原因是数据和程序级别的混合。

我的回答主要基于这里的最高评分,希望每个人都能理解(在我的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函数中简单地返回值,可以复制任何对象。

如果您不仅对值感兴趣,而且对键感兴趣,我已经编写了Object.map(valueMapper,keyMapper),其行为如下:

var source = { a: 1, b: 2 };
function sum(x) { return x + x }

source.map(sum);            // returns { a: 2, b: 4 }
source.map(undefined, sum); // returns { aa: 1, bb: 2 }
source.map(sum, sum);       // returns { aa: 2, bb: 4 }

如果有人在寻找将对象映射到新对象或数组的简单解决方案:

// Maps an object to a new object by applying a function to each key+value pair.
// Takes the object to map and a function from (key, value) to mapped value.
const mapObject = (obj, fn) => {
    const newObj = {};
    Object.keys(obj).forEach(k => { newObj[k] = fn(k, obj[k]); });
    return newObj;
};

// Maps an object to a new array by applying a function to each key+value pair.
// Takes the object to map and a function from (key, value) to mapped value.
const mapObjectToArray = (obj, fn) => (
    Object.keys(obj).map(k => fn(k, obj[k]))
);

这可能不适用于所有对象或所有映射函数,但它适用于简单的浅对象和简单的映射函数,这是我所需要的。

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)。