投影 JavaScript 对象字段的最佳方法是什么?

What is the best way to projecting fields of JavaScript object?

我必须将 javascript 的某些字段投影到新对象。

例如我有一个下面的对象

var obj = { fn : 'Abc', 
            ln : 'Xyz', 
            id : 123, 
            nt : 'Note', 
            sl : 50000}

我想要包含 fn and id

的新对象
var projectedObj = { fn : 'Abc', id : 123 }

基于投影

var projection = { fn : 1, id : 1 }

像这样

var projectedObj = project(obj, projection);

那么执行此操作的最佳方法或优化方法是什么。

只需遍历投影对象并投影键。例如,

function project(obj, projection) {
    let projectedObj = {}
    for(let key in projection) {
        projectedObj[key] = obj[key];
    }
    return projectedObj;
}

您可以 reduce 您的 projection 键返回 obj 值作为:

var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000}
var projection = { fn : 1, id : 1 }

function project(obj, projection) {
  return Object.keys(projection).reduce((a, e) => { a[e] = obj[e]; return a; }, {});
}

console.log(project(obj, projection));

您可以使用 array#reduce 并遍历投影对象的所有键,并根据键从原始对象中提取值并创建新对象。

var project = (o, p) => {
  return Object.keys(p).reduce((r,k) => {
    r[k] = o[k] || '';
    return r;
  },{});
}

var obj = { fn : 'Abc', ln : 'Xyz', id : 123,  nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);

您还可以使用 array#mapObject#assign 来创建新对象。

var project = (o, p) => {
  return Object.assign(...Object.keys(p).map(k => ({[k]: o[k]})));
}

var obj = { fn : 'Abc', ln : 'Xyz', id : 123,  nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);

我是这样做的。它可以处理嵌套对象,但可能无法处理既可以是值也可以是对象的属性。

let entity = {
    timeStamp: "1970-01-01T00:00:00.000Z",
    value: 1,
    itemList: [
        {
            amount: 1,
            product: {
                name: "Product 0",
                _links: { self: { href: "https://example.com:8080/api/entityA/1" } }
            },
            value: 1,
            flag: false,
            _links: { self: { href: "https://example.com:8080/api/entityB/1" } }
        }
    ],
    summerTime: false,
    parent: {
        grandParentA: {
            name: "Grand Parent 0",
            _links: { self: { href: "https://example.com:8080/api/entityC/1" } }
        },
        grandParentB: null,
        name: "Parent 0",
        _links: { self: { href: "https://example.com:8080/api/entityD/1" } }
    },
    _links: { self: { href: "https://example.com:8080/api/entityE/1" } }
};

let entityProjection = {
    parent: {
        grandParentA: {
            _links: { self: { href: false } }
        },
        grandParentB: {
            _links: { self: { href: false } }
        },
        _links: { self: { href: false } }
    },
    _links: { self: { href: false } }
}

const project = (object, projection) => {
    return Object.keys(projection).reduce((a, e) => ({ ...a, [e]: object[e] ? (projection[e] ? project(object[e], projection[e]) : object[e]) : object[e] }), {});
}

console.log(project(entity, entityProjection));

作为不传递投影对象而是将要投影的属性列为逗号分隔字符串的替代方法,此模块可以做到这一点。请注意,此模块不支持对象,而是支持数组。

    var linqmodule = (function() {
  projection = function(members) {
    var membersArray = members.replace(/s/g, "").split(",");
    var projectedObj = {};

    for (var i = 0; i < this.length; i++) {
      for (var j = 0; j < membersArray.length; j++) {
        var key = membersArray[j];
        if (j === 0) {
          projectedObj[i] = {};
        }
        projectedObj[i][key] = this[i][key];
      }
    }

    return projectedObj;
  };
  Array.prototype.select = projection;

  dumpmethod = function(arrayobj) {
    var result = "";
    result += "[";

    for (var i = 0; i < Object.keys(arrayobj).length; i++) {
      var membersArray = Object.keys(arrayobj[i]);
      for (var j = 0; j < membersArray.length; j++) {
        if (j === 0) {
          result += "{";
        }
        var key = membersArray[j];
        result +=
          "key: " +
          key +
          " , value: " +
          arrayobj[i][key] +
          (j < membersArray.length - 1 ? " , " : "");
        if (j === membersArray.length - 1) {
          result +=
            "}" + (i < Object.keys(arrayobj).length - 1 ? "," : "") + "\n";
        }
      }
    }
    result += "]";

    return result;
  };

  return {
    dump: dumpmethod
  };
})();

要投影您的 Json 对象数组,您可以使用此示例作为指南:

var someCountries = [
          { country: "Norway", population: 5.2, code: "NO" },
          { country: "Finland", population: 5.5, code: "SU" },
          { country: "Iceland", population: 0.4, code: "IC" },
          { country: "Sweden", population: 10.2, code: "SW" }
        ];
var result = someNums.select("country,population");
console.log(linqmodule.dump(result));

然后生成的数组包含没有字段 'code' 的投影结果(并复制到新数组中)。

这并没有回答问题,因为它询问的是单个对象和投影对象,但它展示了如何使用对象数组(数组的每个对象中具有相同的字段)实现相同的目的。那么很多人会发现它对类似的场景很有用。