我有一个目标:
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使用这个,所以我不关心跨浏览器问题。)
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)。
这真的很烦人,JS社区的每个人都知道。应该有这样的功能:
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, ctx){
const ret = {};
for(let k of Object.keys(obj)){
ret[k] = fn.call(ctx || null, k, obj[k]);
});
return ret;
};
总是要自己实现这一点非常令人讨厌;)
如果您想要一些更复杂的、不干扰Object类的东西,请尝试以下操作:
let map = function (obj, fn, ctx) {
return Object.keys(obj).reduce((a, b) => {
a[b] = fn.call(ctx || null, b, obj[b]);
return a;
}, {});
};
const x = map({a: 2, b: 4}, (k,v) => {
return v*2;
});
但将此映射函数添加到Object是安全的,只是不要添加到Object.prototype。
Object.map = ... // fairly safe
Object.prototype.map ... // not ok
没有到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))
写一个很简单:
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 }
注意:这个版本还允许您(可选)为回调设置this上下文,就像Array方法一样。
EDIT-更改为删除Object.prototype的使用,以确保它不会与对象上任何现有的名为map的属性冲突。
如果有人在寻找将对象映射到新对象或数组的简单解决方案:
// 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]))
);
这可能不适用于所有对象或所有映射函数,但它适用于简单的浅对象和简单的映射函数,这是我所需要的。