【问题标题】:What is the most efficient way to copy some properties from an object in JavaScript?在 JavaScript 中从对象复制某些属性的最有效方法是什么?
【发布时间】:2016-11-12 12:03:39
【问题描述】:

说,我有一个对象:

const user = {_id: 1234, firstName: 'John', lastName: 'Smith'}

我想创建另一个没有_id 键的对象:

const newUser = {firstName: 'John', lastName: 'Smith'}

我正在使用这个:

const newUser = Object.assign({}, {firstName: user.firstName, lastName: user.lastName})

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: javascript ecmascript-6


    【解决方案1】:

    你可以通过解构的形式来实现它:

    const user = { _id: 1234, firstName: 'John', lastName: 'Smith' };
    const { _id, ...newUser } = user;
    console.debug(newUser); 

    但是,在撰写此答案时,传播 (...) 语法仍处于 ECMAScript proposal 阶段(第 3 阶段),因此在实践中可能无法普遍使用。您可以将它与 Babel 等“转译”层一起使用。

    【讨论】:

    • 目前第4阶段,根据第一个链接
    • 请注意,这也会创建一个_id 变量。
    【解决方案2】:

    Array#reduce 方法和Object.keys 方法来做。

    const user = {
      _id: 1234,
      fistName: 'John',
      lastName: 'Smith'
    };
    
    var res = Object.keys(user).reduce(function(obj, k) {
      if (k != '_id') obj[k] = user[k];
      return obj;
    }, {});
    
    console.log(res);

    【讨论】:

    • 我想知道这怎么能比 OP 所做的分配更快。
    • @trincot - 为什么不阅读这个问题,它说 “我想在没有 _id 键的情况下创建另一个对象”,然后 OP 显示的对象是预期的结果,并继续说他正在使用Object.assign,这不是直接分配。
    • 确实,Object.assign 在 OP 的代码中当然是多余的。
    • @trincot : Object.assign({}, {firstName: user.firstName, lastName: user.lastName}) 与简单分配{firstName: user.firstName, lastName: user.lastName} 相同。我认为他想复制除_id 之外的所有其他属性......以防他不知道是什么有哪些属性?
    • @PranavCBalan,我知道有一个通用的解决方案很好,但 OP 对此并不清楚,因为他似乎有一个具有硬编码属性名称的工作解决方案。对于您的第一个陈述:我同意结果是相同的,但是使用Object.assign 创建了两个新对象(参见两个对象文字)而不是一个,因此浅层副本也被采用了两次,而不是一次。跨度>
    【解决方案3】:

    您要进行两次浅拷贝:一次使用对象字面量,另一次使用Object.assign。所以只需使用两者中的第一个:

    const newUser = {firstName: user.firstName, lastName: user.lastName};
    

    【讨论】:

      【解决方案4】:

      最有效的可能是常规循环

      const user = {_id: 1234, fistName: 'John', lastName: 'Smith'};
      let   obj  = {}, key;
      
      for (key in user) {
        if ( key !== '_id' ) obj[key] = user[key];
      }
      
      console.log(obj)

      【讨论】:

      • 循环如何比 OP 执行的直接赋值更快?
      • @trincot - Object.assign 不是“直接赋值”,它是一种内部方法,它会迭代、执行一些检查并创建一个新对象,而且效率不高 -> @987654321 @。当然,如果操作 can 使用直接分配,并且可以直接引用键,那会更快,但这只是省略了 _id 属性,就像其他答案一样,并假设一个没有总是想使用所有的键。
      • 确实,Object.assign 在 OP 的代码中当然是多余的。
      • @trincot - 当然,由于属性是原语,所以根本不需要 assign 调用,OP 正在将他想要的对象传递给 Object.assign 并获取完全相同的对象,我只是假设重点是在创建新对象时省略_id 属性,而不是直接引用其他属性?
      • 这个问题确实模棱两可。 OP 写道 我目前正在使用这个,如果该解决方案也必须适用于他的代码中具有其他属性的对象,那么这是不可能的。现在不确定。
      【解决方案5】:

      这个小功能将选择特定的键来复制或从复制中排除。排除优先:

      function copy(obj, include=[], exclude=[]) {
      
        return Object.keys(obj).reduce((target, k) => {
      
          if (exclude.length) {
            if (exclude.indexOf(k) < 0) target[k] = obj[k];
          } else if (include.indexOf(k) > -1) target[k] = obj[k];
          return target;
        }, {});
      }
      
      // let's test it
      const user = {
        _id: 1234,
        firstName: 'John',
        lastName: 'Smith'
      };
      
      // both will return the same result but have different uses.
      console.log(
        'include only firstName and lastName:\n', 
        copy(user, ['firstName', 'lastName'])
      );
      console.log(
        'exclude _id:\n',
        copy(user, null, ['_id'])
      );

      【讨论】:

        【解决方案6】:

        检查对象键,将想要的属性键放入一个数组中,然后使用Array.prototype.includes() 仅将这些复制到新对象中。

        const account = {
          id: 123456,
          firstname: "John",
          lastname: "Doe",
          login: "john123",
          site_admin: false,
          blog: "https://opensource.dancingbear/",
          email: "john123@example.com",
          bio: "John ❤️ Open Source",
          created_at: "2001-01-01T01:30:18Z",
          updated_at: "2020-02-16T21:09:14Z"
        };
        
        function selectSomeProperties(account) {
        return Object.keys(account).reduce(function(obj, k) {
            if (["id", "email", "created_at"].includes(k)) {
                obj[k] = account[k];
            }
            return obj;
          }, {});
        }
        const selectedProperties = selectSomeProperties(account);
        console.log(JSON.stringify(selectedProperties))

        结果:

        {"id":123456,"email":"john123@example.com","created_at":"2001-01-01T01:30:18Z"}
        

        【讨论】:

          猜你喜欢
          • 2021-08-30
          • 2020-05-26
          • 2011-08-04
          • 2023-03-23
          • 2021-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-10
          相关资源
          最近更新 更多