在Javascript中编写部分复制对象的优雅方式?

在Javascript中编写部分复制对象的优雅方式?,javascript,Javascript,我有一个表示表单字段的javascript对象。其中大约70%的字段必须复制到某些对象中才能发送到服务器,其他字段用于UI。目前,我通过手动为每个字段创建分配来克隆对象,这会导致不太好的结构,如下所示。请注意,对于要复制的部件,我将保持字段名称相同 var contData = { ContainerType: data.ContainerType, ProjectIds: data.ProjectIds,

我有一个表示表单字段的javascript对象。其中大约70%的字段必须复制到某些对象中才能发送到服务器,其他字段用于UI。目前,我通过手动为每个字段创建分配来克隆对象,这会导致不太好的结构,如下所示。请注意,对于要复制的部件,我将保持字段名称相同

var contData = {
                ContainerType: data.ContainerType,
                ProjectIds: data.ProjectIds,
                PrivateToProjects: data.PrivateToProjects,
                DimensionType:data.DimensionType,
                MetricsX: data.MetricsX,
                MetricsY: data.MetricsY,
                Parent:data.Parent,
                ContainerName:data.Prefix
            };
对对象的克隆部分进行编码的最佳方法是什么,只需指定要克隆/不要克隆的字段列表,例如一些有用的辅助函数


我还使用angular和jquery。

您可以创建一个自定义函数,使用过滤函数部分克隆对象

它可以是这样一个非常简单的版本

function filteredClone(sourceObj, filterFunction){
  var destObj = {};
  for(var i in sourceObj){
    if(filterFunction(sourceObj[i])){
      destObj[i] = sourceObj[i];
    }
  }
  return destObj;
}
假设您不想复制“name”和“姓氏”字段,您可以像下面这样调用它

var dest = filteredClone(source, function(v){
   return ["name","surname"].indexOf(v) !== -1;
});
以下问题的答案中有几个更复杂的例子


您可以创建一个自定义函数,使用筛选函数部分克隆对象

它可以是这样一个非常简单的版本

function filteredClone(sourceObj, filterFunction){
  var destObj = {};
  for(var i in sourceObj){
    if(filterFunction(sourceObj[i])){
      destObj[i] = sourceObj[i];
    }
  }
  return destObj;
}
假设您不想复制“name”和“姓氏”字段,您可以像下面这样调用它

var dest = filteredClone(source, function(v){
   return ["name","surname"].indexOf(v) !== -1;
});
以下问题的答案中有几个更复杂的例子


一种方法是定义对象的属性。IE9是第一个支持这一点的IE

var obj = {};
Object.defineProperty(obj, "no1", {enumerable: false, value: "", writable: true, configurable: true});
Object.defineProperty(obj, "no2", {enumerable: false, value: "", writable: true, configurable: true});

obj.yes1 = "foo";
obj.yes2 = "bar";
obj.no1 = "baz";
obj.no2 = "quux";

99.9%的克隆函数将在键上循环,并且只显示可枚举键,因此它们只复制可枚举键。这与循环对象关键帧时,例如
toString
不会显示的原因相同

这可以抽象为允许定义数据和临时值

function makeType(description, data) {
    if (arguments.length === 1) {
        return function (data) {
            return makeType.call(this, description, data);
        };
    }

    var obj = {};
    data = data || {};
    for (var key in description) {
        if (description[key] === true) {
            obj[key] = data[key]
        } else {
            Object.defineProperty(obj, key, {
                enumerable: false,
                value: data[key],
                writable: true,
                configurable: true
            });
        }
    }
    return obj;
}

var makeYesNo = makeType({
    yes1: true,
    yes2: true,
    no1: false,
    no2: false
});

var obj = makeYesNo({
    yes1: "foo",
    yes2: "bar",
    no1: "baz",
    no2: "quux"
})

一种方法是定义对象的属性。IE9是第一个支持这一点的IE

var obj = {};
Object.defineProperty(obj, "no1", {enumerable: false, value: "", writable: true, configurable: true});
Object.defineProperty(obj, "no2", {enumerable: false, value: "", writable: true, configurable: true});

obj.yes1 = "foo";
obj.yes2 = "bar";
obj.no1 = "baz";
obj.no2 = "quux";

99.9%的克隆函数将在键上循环,并且只显示可枚举键,因此它们只复制可枚举键。这与循环对象关键帧时,例如
toString
不会显示的原因相同

这可以抽象为允许定义数据和临时值

function makeType(description, data) {
    if (arguments.length === 1) {
        return function (data) {
            return makeType.call(this, description, data);
        };
    }

    var obj = {};
    data = data || {};
    for (var key in description) {
        if (description[key] === true) {
            obj[key] = data[key]
        } else {
            Object.defineProperty(obj, key, {
                enumerable: false,
                value: data[key],
                writable: true,
                configurable: true
            });
        }
    }
    return obj;
}

var makeYesNo = makeType({
    yes1: true,
    yes2: true,
    no1: false,
    no2: false
});

var obj = makeYesNo({
    yes1: "foo",
    yes2: "bar",
    no1: "baz",
    no2: "quux"
})

在ES6之后,您可以

let { ContainerType, ProjectIds } = data  // the fields you want
let partiallyCopy = { ContainerType, ProjectIds }
console.log(partiallyCopy)  // { ContainerType: "...", ProjectIds: "..." }
let { ContainerType, ProjectIds, ...rest } = data  // the fields you don't want
let partiallyCopy = rest
console.log(partiallyCopy)  // the object excludes ContainerType and ProjectIds
如果您需要大多数字段,您可以

let { ContainerType, ProjectIds } = data  // the fields you want
let partiallyCopy = { ContainerType, ProjectIds }
console.log(partiallyCopy)  // { ContainerType: "...", ProjectIds: "..." }
let { ContainerType, ProjectIds, ...rest } = data  // the fields you don't want
let partiallyCopy = rest
console.log(partiallyCopy)  // the object excludes ContainerType and ProjectIds
在ES6之后,你可以

let { ContainerType, ProjectIds } = data  // the fields you want
let partiallyCopy = { ContainerType, ProjectIds }
console.log(partiallyCopy)  // { ContainerType: "...", ProjectIds: "..." }
let { ContainerType, ProjectIds, ...rest } = data  // the fields you don't want
let partiallyCopy = rest
console.log(partiallyCopy)  // the object excludes ContainerType and ProjectIds
如果您需要大多数字段,您可以

let { ContainerType, ProjectIds } = data  // the fields you want
let partiallyCopy = { ContainerType, ProjectIds }
console.log(partiallyCopy)  // { ContainerType: "...", ProjectIds: "..." }
let { ContainerType, ProjectIds, ...rest } = data  // the fields you don't want
let partiallyCopy = rest
console.log(partiallyCopy)  // the object excludes ContainerType and ProjectIds

对您是否尝试过编写这样的助手函数?事实上,这很琐碎。我认为angular或jquery中还没有。您是否尝试过编写这样的助手函数?事实上,这很琐碎。我认为angular或jquery中还没有。