【问题标题】:Cloning a TypeScript Object克隆 TypeScript 对象
【发布时间】:2017-02-11 11:56:17
【问题描述】:

我有一个打字稿课

export class Restaurant {

  constructor ( private id: string, private name: string ) {

  }

  public getId() : string {
    return this.id;
  }

  public setId(_id : string) {
    this.id = _id;
  }

  public getName () {
    return this.name;
  }

  public setName ( _name:string ) {
    this.name = _name;
  }

}

然后我有这个类的一个实例(这是一个例子):

restaurant:Restaurant = new Restaurant(1,"TestRest");

然后我将这个餐厅对象存储在某种缓存中

cache.store( restaurant );

然后在我的申请中,我把餐厅找回来了

var restToEdit = cache.get( "1" );
restToEdit.setName( "NewName" );

但是由于 javascripts 通过对象的引用传递,我对 restToEdit 所做的更改也会保存在缓存中的餐厅中。

我基本上希望缓存中的餐厅与 restToEdit 完全不同。

我尝试过使用 jQuery.clone 和 extend,但它似乎不起作用,我认为这是因为它是一个 typescript 对象。还是那不重要?

任何关于如何克隆此对象的答案将不胜感激

谢谢

【问题讨论】:

    标签: javascript typescript clone


    【解决方案1】:
    • 使用标准ES6 features

      const clone = Object.assign({}, myObject)
      

      警告:这会执行浅层克隆。

      excellent page from MDN 包含大量关于克隆的详细信息,包括 ES5 的 polyfill

    • 深度克隆的“快速”方法是使用JSON 实用程序

      const clone = JSON.parse(JSON.stringify(myObject))
      
    • “正确”的克隆方式是实现克隆方法或复制构造函数...

    我知道,我知道,not enough JQuery

    【讨论】:

    • Object.assign 复制参考。
    • 使用 Json.parse 然后 Json.stringify 会丢失分配给对象的函数
    • @JaganathanBantheswaran ...如果您的浅克隆或克隆不可变属性,这非常好!
    • 在 Typescript 中使用 Object.assign 感觉不对。显然,我知道一旦它编译成 js 就可以了,但我觉得这不是我的解决方案,即使我想要一个深度克隆,正如我解释的那样,属性不是不可变的
    • @JaganathanBantheswaran angular.copy 在 angular 2 中不可用
    【解决方案2】:

    这似乎对我有用:

    var newObject = Object.assign(Object.create(oldObj), oldObj)
    

    Object.create 创建一个具有空属性的新实例 Object.assign 然后获取该新实例并分配属性

    更强大的克隆函数版本

        clone(obj) {
            if(Array.isArray(obj)) {
                return Array.from(obj);
            } else {
                return Object.assign(Object.create(obj), obj);
            }
        }
    

    【讨论】:

    • 只做浅层克隆。任何引用仍然指向与原始对象相同的对象。
    • 我建议使用Object.create(Object.getPrototypeOf(obj)) 而不是Object.create(obj)。当前代码有下一个问题:如果obj 在复制期间有一个属性是undefined,那么在将此属性更改为原始obj 中的某个值后,克隆将看到更改。
    【解决方案3】:

    如果您使用的是 TS 2.1,则可以使用对象扩展运算符来创建浅拷贝:

    const obj = { a: 1 };
    const clonedObj = { ...obj };
    

    【讨论】:

      【解决方案4】:

      .clone() 只克隆 DOM 元素。为了克隆 JavaScript 对象,请尝试jQuery.extend。像这样的

      // Shallow copy
      var newObject = jQuery.extend({}, oldObject);
      
      // Deep copy
      var newObject = jQuery.extend(true, {}, oldObject);
      

      Typescript 转换为 JavaScript。因此,JavaScript 方式可以正常工作。

      演示:

      // Transpiled version of TypeScript
      "use strict";
          var Restaurant = (function () {
              function Restaurant(id, name) {
                  this.id = id;
                  this.name = name;
              }
              Restaurant.prototype.getId = function () {
                  return this.id;
              };
              Restaurant.prototype.setId = function (_id) {
                  this.id = _id;
              };
              Restaurant.prototype.getName = function () {
                  return this.name;
              };
              Restaurant.prototype.setName = function (_name) {
                  this.name = _name;
              };
              return Restaurant;
          }());
      
      // Test Snippet
      var r1 = new Restaurant(1, "A");
      var r2 = jQuery.extend(true, {}, r1);
      
      r2.setName("B");
      
      console.log(r1.name);
      console.log(r2.name);
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

      【讨论】:

      • 谢谢,这行得通。只是觉得打字稿不太对劲。我不喜欢在打字稿中使用 Javascript 代码,因为我知道它会起作用。但就目前而言,这似乎是唯一的解决方案。谢谢
      • 你可以把它包装在类/原型上:public clone(): Restaurant { /* same jquery code, just return r2 */ }
      猜你喜欢
      • 2017-06-13
      • 2021-01-07
      • 2018-05-26
      • 2019-03-02
      • 2011-11-07
      • 2013-01-03
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多