Angular 2中复制对象的最佳方法是什么?

3

Angular 1.x全局angular对象有许多方法,如angular.copy、angular.shallowCopy(还有其他方法如angular.forEach),在Angular 2中似乎没有相应的版本。也许它只是没有被记录下来。如果Angular 2不打算提供这些实用工具,那么获取该功能的最佳方式是什么?

我知道我可以使用来自Angular 1.x的逻辑来编写自己的浅拷贝方法:

function shallowCopy(src, dst) {
  if (isArray(src)) {
    dst = dst || [];

    for (var i = 0, ii = src.length; i < ii; i++) {
      dst[i] = src[i];
    }
  } else if (isObject(src)) {
    dst = dst || {};

    for (var key in src) {
      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
        dst[key] = src[key];
      }
    }
  }

  return dst || src;
}

但是深拷贝逻辑要复杂得多(显然)

2个回答

1
当对象是一个数组时,我使用以下代码: copyOfArray = originalArray.slice(0, originalArray.length); 其中originalArray是原始数组对象。
内置的javascript array.slice(start, end)函数返回一个子数组作为新的数组对象(JavaScript Array slice() Method)。将开始和结束边界设置为原始数组的大小会返回整个数组的副本。

0
为什么不直接复制 Angular 1 的复制函数?
从源代码中(需要适应一些东西,比如调用错误处理程序,但基本上是这样的:)
function copy(source, destination, stackSource, stackDest) {
  if (isWindow(source) || isScope(source)) {
    throw ngMinErr('cpws',
      "Can't copy! Making copies of Window or Scope instances is not supported.");
  }
  if (isTypedArray(destination)) {
    throw ngMinErr('cpta',
      "Can't copy! TypedArray destination cannot be mutated.");
  }

  if (!destination) {
    destination = source;
    if (isObject(source)) {
      var index;
      if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
        return stackDest[index];
      }

      // TypedArray, Date and RegExp have specific copy functionality and must be
      // pushed onto the stack before returning.
      // Array and other objects create the base object and recurse to copy child
      // objects. The array/object will be pushed onto the stack when recursed.
      if (isArray(source)) {
        return copy(source, [], stackSource, stackDest);
      } else if (isTypedArray(source)) {
        destination = new source.constructor(source);
      } else if (isDate(source)) {
        destination = new Date(source.getTime());
      } else if (isRegExp(source)) {
        destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
        destination.lastIndex = source.lastIndex;
      } else if (isFunction(source.cloneNode)) {
          destination = source.cloneNode(true);
      } else {
        var emptyObject = Object.create(getPrototypeOf(source));
        return copy(source, emptyObject, stackSource, stackDest);
      }

      if (stackDest) {
        stackSource.push(source);
        stackDest.push(destination);
      }
    }
  } else {
    if (source === destination) throw ngMinErr('cpi',
      "Can't copy! Source and destination are identical.");

    stackSource = stackSource || [];
    stackDest = stackDest || [];

    if (isObject(source)) {
      stackSource.push(source);
      stackDest.push(destination);
    }

    var result, key;
    if (isArray(source)) {
      destination.length = 0;
      for (var i = 0; i < source.length; i++) {
        destination.push(copy(source[i], null, stackSource, stackDest));
      }
    } else {
      var h = destination.$$hashKey;
      if (isArray(destination)) {
        destination.length = 0;
      } else {
        forEach(destination, function(value, key) {
          delete destination[key];
        });
      }
      if (isBlankObject(source)) {
        // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
        for (key in source) {
          destination[key] = copy(source[key], null, stackSource, stackDest);
        }
      } else if (source && typeof source.hasOwnProperty === 'function') {
        // Slow path, which must rely on hasOwnProperty
        for (key in source) {
          if (source.hasOwnProperty(key)) {
            destination[key] = copy(source[key], null, stackSource, stackDest);
          }
        }
      } else {
        // Slowest path --- hasOwnProperty can't be called as a method
        for (key in source) {
          if (hasOwnProperty.call(source, key)) {
            destination[key] = copy(source[key], null, stackSource, stackDest);
          }
        }
      }
      setHashKey(destination,h);
    }
  }
  return destination;
}

1
我知道我可以像我在问题中提到的那样复制Angular 1版本。但是问题是是否这是最好的方法。如果你查看那段代码,你会发现有很多调用其他方法的调用也必须被复制(isArray,isTypedArray,isDate,isRegExp等)。走这条路其实也是可以的,但如果Angular 2将要有某种类来处理它,那就更好了。或者可能有其他首选库可用。 - mcgraphix
深拷贝在任何复杂应用程序中都是必需的,因此您需要一个执行此操作的方法。现在,您可以使用jQuery的深度扩展,或者如果您喜欢,可以使用lodash的cloneDeep而不是复制粘贴ng1方法... - Pierre Gayvallet
是的...我最初只使用jQuery,但如果Angular包含一种方法来完成它,那会更好,这样你就不必依赖于另一个库。 - mcgraphix
像这样导入isArray和isDate:import { isArray, isDate } from '@angular/core/src/facade/lang';似乎可以工作。可能有一个对象克隆实用程序,但尚未记录。 - Jack Vial

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接