我有一个目标:

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


当前回答

公认的答案有两个缺点:

它误用了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指定了迭代器和可迭代协议。但对象仍然不可迭代,因此不可映射。原因是数据和程序级别的混合。

其他回答

写一个很简单:

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的属性冲突。

根据@Amberlamps的回答,这里有一个实用函数(作为评论,它看起来很难看)

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}

为了更准确地响应OP的要求,OP需要一个对象:

myObject={“a”:1,“b”:2,“c”:3}

要使用映射方法myObject.map,

类似于Array.prototype.map,使用如下:newObject=myObject.map(函数(值,标签){返回值*值;});//newObject现在是{“a”:1,“b”:4,“c”:9}

imho最佳答案(以“接近要求的内容”+“不需要ES{5,6,7}”来衡量)是:

myObject.map = function mapForObject(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property) && property != "map"){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

上面的代码避免故意使用任何语言特性,这些特性仅在最近的ECMAScript版本中可用。使用上面的代码,问题可以通过以下方式解决:

myObject={“a”:1,“b”:2,“c”:3};myObject.map=函数mapForObject(回调){var结果={};for(此中的var属性){如果(this.hasOwnProperty(property)&&property!=“地图”){result[property]=回调(this[property],property,this);}}返回结果;}newObject=myObject.map(函数(值,标签){返回值*值;});console.log(“newObject is now”,newObject);此处为备选测试代码

除了受到一些人的反对外,还可以像这样将解决方案插入到原型链中。

Object.prototype.map = function(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property)){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

在仔细监督的情况下进行的操作不会产生任何不良影响,也不会影响其他对象的贴图方法(即阵列的贴图)。

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 }

Hey编写了一个可能有帮助的小映射器函数。

    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];
                }
              }
            }
         }
      }