映射函数的对象(而不是数组)

我有一个对象:

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是否具有对象的mapfunction? (我想要这个Node.JS,所以我不关心跨浏览器的问题。)

Object对象没有本地map ,但是这个如何:

 Object.keys(myObject).map(function(key, index) { myObject[key] *= 2; }); console.log(myObject); // => { 'a': 2, 'b': 4, 'c': 6 } 

但是你可以很容易地迭代一个对象使用for ... in

 for(var key in myObject) { if(myObject.hasOwnProperty(key)) { myObject[key] *= 2; } } 

更新

很多人都提到,以前的方法不会返回一个新的对象,而是对对象本身进行操作。 对于这个问题,我想添加另一个解决scheme,返回一个新的对象,并保持原来的对象,因为它是:

 var newObject = Object.keys(myObject).reduce(function(previous, current) { previous[current] = myObject[current] * myObject[current]; return previous; }, {}); console.log(newObject); // => { 'a': 1, 'b': 4, 'c': 9 } console.log(myObject); // => { 'a': 1, 'b': 2, 'c': 3 } 

Array.prototype.reduce通过将前一个值与当前值相结合,将数组减less为单个值。 链由空对象{}初始化。 在每次迭代中, myObject的新密钥都以其平方值作为值添加。

没有本地方法,但lodash#mapValues将做出出色的工作

 _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); // → { 'a': 3, 'b': 6, 'c': 9 } 

如何在简单的JS( ES6 / ES2015 )即时variables赋值的单线程

使用扩展运算符和计算键名称语法:

 let newObj = Object.assign({}, ...Object.keys(obj).map(k => ({[k]: obj[k] * obj[k]}))); 

jsbin

另一个版本使用reduce:

 let newObj = Object.keys(obj).reduce((p, c) => ({...p, [c]: obj[c] * obj[c]}), {}); 

jsbin

作为函数的第一个例子:

 const oMap = (o, f) => Object.assign(...Object.keys(o).map(k => ({ [k]: f(o[k]) }))); // To square each value you can call it like this: let mappedObj = oMap(myObj, (x) => x * x); 

jsbin

如果您想以function样式recursion地映射嵌套对象,可以这样做:

 const sqrObjRecursive = (obj) => Object.keys(obj).reduce((newObj, key) => (obj[key] && typeof obj[key] === 'object') ? {...newObj, [key]: sqrObjRecursive(obj[key])} : // recurse. {...newObj, [key]: obj[key] * obj[key]} // square val. ,{}) 

jsbin

更重要的是,像这样:

 const sqrObjRecursive = (obj) => { Object.keys(obj).forEach(key => { if (typeof obj[key] === 'object') obj[key] = sqrObjRecursive(obj[key]); else obj[key] = obj[key] * obj[key] }); return obj; }; 

jsbin

由于ES7 / ES2016可以使用Object.entries而不是Object.keys例如:

 let newObj = Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v}))); 

inheritance的属性和原型链:

在一些罕见的情况下,您可能需要映射一个对象, 该类对象在其原型链上保存了一个inheritance对象的属性。 在这种情况下, Object.keys()将不起作用,因为Object.keys()不枚举inheritance的属性。 如果你需要映射inheritance的属性,你应该使用for (key in myObj) {...}

下面是一个inheritance另一个对象属性的对象的例子,以及Object.keys()在这种情况下不起作用的例子。

 const obj1 = { 'a': 1, 'b': 2, 'c': 3} const obj2 = Object.create(obj1); // One of multiple ways to inherit an object in JS. // Here you see how the properties of obj1 sit on the 'prototype' of obj2 console.log(obj2) // Prints: obj2.__proto__ = { 'a': 1, 'b': 2, 'c': 3} console.log(Object.keys(obj2)); // Prints: an empty Array. for (key in obj2) { console.log(key); // Prints: 'a', 'b', 'c' } 

jsbin

但是,请帮我一个忙,避免inheritance 。 🙂

写一个很容易:

 Object.map = function(o, f, ctx) { ctx = ctx || this; var result = {}; Object.keys(o).forEach(function(k) { result[k] = f.call(ctx, o[k], k, o); }); return result; } 

用示例代码:

 > o = { a: 1, b: 2, c: 3 }; > r = Object.map(o, function(v, k, o) { return v * v; }); > r { a : 1, b: 4, c: 9 } 

注意:这个版本还允许你(可选地)为callback设置this上下文,就像Array方法一样。

编辑 – 更改为删除使用Object.prototype ,以确保它不与任何现有属性名为map上的对象冲突。

您可以使用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..in循环中的hasOwnProperty检查。

我来到这里寻找和回答映射一个对象到一个数组,并得到这个页面作为结果。 如果你来到这里寻找同样的答案,那么这里是你如何映射和对象到一个数组。

你可以使用map从对象返回一个新的数组,像这样:

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

被接受的答案有两个缺点:

  • 它滥用Array.prototype.reduce ,因为减less意味着改变一个复合types的结构,在这种情况下不会发生。
  • 它不是特别可重用的

ES6 / ES2015function方法

请注意,所有function都以咖啡forms定义。

 // small, reusable auxiliary functions const keys = o => Object.keys(o); const assign = (...o) => Object.assign({}, ...o); const map = f => xs => xs.map(x => f(x)); const mul = y => x => x * y; const sqr = x => mul(x) (x); // the actual map function const omap = f => o => { o = assign(o); // A map(x => o[x] = f(o[x])) (keys(o)); // B return o; }; // mock data const o = {"a":1, "b":2, "c":3}; // and run console.log(omap(sqr) (o)); console.log(omap(mul(10)) (o)); 

这是简单的,JS社区里的每个人都知道。 应该有这个function:

 const obj1 = {a:4, b:7}; const obj2 = Object.map(obj1, (k,v) => v + 5); console.log(obj1); // {a:4, b:7} console.log(obj2); // {a:9, b:12} 

这里是天真的实现:

 Object.map = function(obj, fn){ const ret = {}; Object.keys(obj).forEach(function(k){ ret[k] = fn.call(null,k,obj[k]); }); return ret; }; 

这是非常烦人的,必须自己实现这一点;)

为了获得最佳性能

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

 // example object var obj = {a: 1, b: 2, c: 'something'}; // caching map var objMap = new Map(Object.entries(obj)); // fast iteration on Map object objMap.forEach((item, key) => { // do something with an item console.log(key, item); }); 

为什么不在戒指里戴另一顶帽子?

 // pair :: (a,b) -> Pair const pair = (x,y) => [x,y] // keys :: Object(k:a) -> [k] const keys = Object.keys // oreduce :: (a -> Pair(k,b) -> a) -> a -> Object(k:b) -> a const oreduce = f => acc => o => { let loop = (acc, [k,...ks]) => k === undefined ? acc : loop (f (acc) (pair (k, o[k])), ks) return loop (acc, keys (o)) } // omap :: (Pair(k,a) -> b) -> Object(k:a) -> Object(k:b) const omap = f => oreduce (acc => ([k,v]) => Object.assign(acc, { [k]: f(v) }) ) ({}) // pairs :: Object(k:a) -> [Pair(k,a)] const pairs = oreduce(acc=> pair=> [...acc, pair]) ([]) // DEMONSTRATION let o = {a: 1, b: 2, c: 3} console.log(omap (x => x * 3) (o)) // => { a: 3, b: 6, c: 9 } console.log(oreduce (s=> ([k,v])=> s + `&${k}=${v}`) ('?') (o)) // => ?&a=1&b=2&c=3 console.log(pairs(o)) // => [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ] 

基于@Amberlamps答案,这里是一个实用function(作为一个看起来丑陋的评论)

 function mapObject(obj, mapFunc){ return Object.keys(obj).reduce(function(newObj, value) { newObj[value] = mapFunc(obj[value]); return newObj; }, {}); } 

用途是:

 var obj = {a:1, b:3, c:5} function double(x){return x * 2} var newObj = mapObject(obj, double); //=> {a: 2, b: 6, c: 10} 

最小版本(es6):

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

Object.prototype上的map function不存在,但是您可以像这样模拟它

 var myMap = function ( obj, callback ) { var result = {}; for ( var key in obj ) { if ( Object.prototype.hasOwnProperty.call( obj, key ) ) { if ( typeof callback === 'function' ) { result[ key ] = callback.call( obj, obj[ key ], key, obj ); } } } return result; }; var myObject = { 'a': 1, 'b': 2, 'c': 3 }; var newObject = myMap( myObject, function ( value, key ) { return value * value; }); 
 var myObject = { 'a': 1, 'b': 2, 'c': 3 }; Object.prototype.map = function(fn){ var oReturn = {}; for (sCurObjectPropertyName in this) { oReturn[sCurObjectPropertyName] = fn(this[sCurObjectPropertyName], sCurObjectPropertyName); } return oReturn; } Object.defineProperty(Object.prototype,'map',{enumerable:false}); newObject = myObject.map(function (value, label) { return value * value; }); // newObject is now { 'a': 1, 'b': 4, 'c': 9 } 

如果你对map ping不仅Object.map(valueMapper, keyMapper)而且对键也有兴趣,我写了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 } 

嗨写了一个小的mapper函数可能会有所帮助。

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

编辑:稍微改变,传入起始对象{}。 允许它是[](如果键是整数)

我特别想使用与单个对象的数组相同的function,并希望保持简单。 这对我工作:

 var mapped = [item].map(myMapFunction).pop(); 

我知道这是一个古老的问题,但其中一些答案太长而且复杂。

您可以通过有序对使用简单的for-in循环。 下面的代码适合你的数组对象。 hasOwnProperty()是因为您为对象创build了三个属性(包含值)。

 var myObject = { 'a': 1, 'b': 2, 'c': 3 } function getValue(key) { for (var k in myObject ) { if (myObject.hasOwnProperty(key)) { return myObject[key]; } } } 
 Input: <input id="input" value="" placeholder="a, b or c"><br> Output:<input id="output"><br> <button onclick="output.value=getValue(input.value)" >Get value</button>