我有一个目标:

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


当前回答

JS ES10/ES2019中的一行怎么样?

使用Object.entries()和Object.fromEntries():

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

同样的东西写为函数:

function objMap(obj, func) {
  return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, func(v)]));
}

// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);

此函数还使用递归对嵌套对象进行平方:

function objMap(obj, func) {
  return Object.fromEntries(
    Object.entries(obj).map(([k, v]) => 
      [k, v === Object(v) ? objMap(v, func) : func(v)]
    )
  );
}

// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);

对于ES7/ES2016,您不能使用Objects.fromEntries,但可以使用Object.assign结合排列运算符和计算的关键字名称语法实现相同的功能:

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

ES6/ES2015不允许Object.entries,但可以改用Object.keys:

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

ES6还为。。。循环,允许更命令式的样式:

let newObj = {}

for (let [k, v] of Object.entries(obj)) {
  newObj[k] = v * v;
}


array.reduce()

您也可以使用reduce代替Object.fromEntries和Object.assign:

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


继承的财产和原型链:

在一些罕见的情况下,您可能需要映射一个类类对象,该类对象在其原型链上保存继承对象的财产。在这种情况下,Object.keys()和Object.entries()将无法工作,因为这些函数不包括原型链。

如果需要映射继承的财产,可以使用for(myObj中的键){…}。

以下是此类情况的示例:

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.
console.log(Object.entries(obj2));  // Prints: an empty Array.

for (let key in obj2) {
  console.log(key);              // Prints: 'a', 'b', 'c'
}

不过,请帮我一个忙,避免继承

其他回答

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

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

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

没有到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))

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

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

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”函数

ES6:

Object.prototype.map = function(mapFunc) {
    return Object.keys(this).map((key, index) => mapFunc(key, this[key], index));
}

2015年:

Object.prototype.map = function (mapFunc) {
    var _this = this;

    return Object.keys(this).map(function (key, index) {
        return mapFunc(key, _this[key], index);
    });
};

节点中的测试:

> a = {foo: "bar"}
{ foo: 'bar' }
> a.map((k,v,i) => v)
[ 'bar' ]

如果您不仅对值感兴趣,而且对键感兴趣,我已经编写了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 }