我有一个目标:
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使用这个,所以我不关心跨浏览器问题。)
如果有人在寻找将对象映射到新对象或数组的简单解决方案:
// 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]))
);
这可能不适用于所有对象或所有映射函数,但它适用于简单的浅对象和简单的映射函数,这是我所需要的。
TypeScript中的对象映射器
我喜欢像这样使用Object.fromEntries的示例,但它们仍然不太好用。使用Object.keys然后查找关键字的答案实际上是在进行可能不需要的多次查找。
我希望有一个Object.map函数,但我们可以创建自己的函数,并将其称为objectMap,同时可以修改键和值:
用法(JavaScript):
const myObject = { 'a': 1, 'b': 2, 'c': 3 };
// keep the key and modify the value
let obj = objectMap(myObject, val => val * 2);
// obj = { a: 2, b: 4, c: 6 }
// modify both key and value
obj = objectMap(myObject,
val => val * 2 + '',
key => (key + key).toUpperCase());
// obj = { AA: '2', BB: '4', CC: '6' }
代码(TypeScript):
interface Dictionary<T> {
[key: string]: T;
}
function objectMap<TValue, TResult>(
obj: Dictionary<TValue>,
valSelector: (val: TValue, obj: Dictionary<TValue>) => TResult,
keySelector?: (key: string, obj: Dictionary<TValue>) => string,
ctx?: Dictionary<TValue>
) {
const ret = {} as Dictionary<TResult>;
for (const key of Object.keys(obj)) {
const retKey = keySelector
? keySelector.call(ctx || null, key, obj)
: key;
const retVal = valSelector.call(ctx || null, obj[key], obj);
ret[retKey] = retVal;
}
return ret;
}
如果您没有使用TypeScript,请在TypeScript Playground中复制上述代码以获取JavaScript代码。
此外,我在参数列表中将keySelector放在valSelector之后的原因是它是可选的。
*亚历山大·米尔斯的回答值得称赞。
如果您不仅对值感兴趣,而且对键感兴趣,我已经编写了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 }
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}]}]}
此函数递归地遍历对象和对象数组。如果返回未定义,则可以删除属性
settings = {
message_notification: {
value: true,
is_active: true,
slug: 'message_notification',
title: 'Message Notification'
},
support_notification: {
value: true,
is_active: true,
slug: 'support_notification',
title: 'Support Notification'
},
};
let keys = Object.keys(settings);
keys.map(key=> settings[key].value = false )
console.log(settings)