什么是替代的角度。复制在角度

我怎样才能复制一个对象,并失去了它的角度参考?

在 AngularJS 中,我可以使用 angular.copy(object),但是我在使用 AngularJS 时会得到一些错误。

异常: ReferenceError: 未定义 angular

164159 次浏览

假设您正在使用 ES6,则可以使用 var copy = Object.assign({}, original)。适用于现代浏览器; 如果您需要支持较老的浏览器,请查看这个 填料

更新:

使用 TypeScript 2.1 + ,ES6可以使用对象扩展速记法:

const copy = { ...original }

在我们找到更好的解决方案之前,你可以使用以下方法:

duplicateObject = <YourObjType> JSON.parse(JSON.stringify(originalObject));

编辑: 澄清

请注意: 上述解决方案只是一个快速修复一个班轮,提供的时候,角2正在积极开发。我希望我们最终能得到相当于 angular.copy()的东西。因此,我不想编写或导入深度克隆库。

此方法还存在解析日期属性的问题(它将成为一个字符串)。

请不要在生产应用程序 中使用此方法。只在你的实验项目中使用它——那些你正在为学习角度2而做的项目。

按照 Bertandg 的指示使用 loash。角度不再有这种方法的原因是,角度1是一个独立的框架,外部库经常遇到与角度执行上下文有关的问题。角度2没有这个问题,所以使用任何你想要的库。

Https://lodash.com/docs#clonedeep

对于 肤浅的复制,您可以使用 Object.sign,它是 ES6的一个特性

let x = { name: 'Marek', age: 20 };
let y = Object.assign({}, x);
x === y; //false

不要用它进行深度克隆

如果你想复制一个类实例,你也可以使用 Object.sign,但是你需要传递一个新的实例作为第一个参数(而不是{}) :

class MyClass {
public prop1: number;
public prop2: number;


public summonUnicorn(): void {
alert('Unicorn !');
}
}


let instance = new MyClass();
instance.prop1 = 12;
instance.prop2 = 42;


let wrongCopy = Object.assign({}, instance);
console.log(wrongCopy.prop1); // 12
console.log(wrongCopy.prop2); // 42
wrongCopy.summonUnicorn() // ERROR : undefined is not a function


let goodCopy = Object.assign(new MyClass(), instance);
console.log(goodCopy.prop1); // 12
console.log(goodCopy.prop2); // 42
goodCopy.summonUnicorn() // It works !

正如其他人已经指出的,使用 loash 或下划线可能是最好的解决方案。但是如果你不需要这些库来做其他事情,你可以使用这样的东西:

  function deepClone(obj) {


// return value is input is not an Object or Array.
if (typeof(obj) !== 'object' || obj === null) {
return obj;
}


let clone;


if(Array.isArray(obj)) {
clone = obj.slice();  // unlink Array reference.
} else {
clone = Object.assign({}, obj); // Unlink Object reference.
}


let keys = Object.keys(clone);


for (let i=0; i<keys.length; i++) {
clone[keys[i]] = deepClone(clone[keys[i]]); // recursively unlink reference to nested objects.
}


return clone; // return unlinked clone.


}

我们就是这么决定的。

我找到的最简单的解决办法是:

let yourDeepCopiedObject = _.cloneDeep(yourOriginalObject);

* 重要步骤: 您必须安装 loash 才能使用这个选项(其他答案不清楚) :

$ npm install --save lodash


$ npm install --save @types/lodash

然后导入到你的文件中:

import * as _ from "lodash";

深度复制内部嵌套对象的另一种方法是使用 loash 的 cloneDeep 方法。

对于 Angular,你可以这样做:

安装带有 yarn add lodashnpm install lodash的浮标。

在组件中,导入 cloneDeep并使用它:

import { cloneDeep } from "lodash";
...
clonedObject = cloneDeep(originalObject);

它只是18kb 添加到您的构建,很值得的好处。

我还写了一个 文章,如果你需要更多的见解,为什么使用 loash 的克隆深。

我需要这个功能只是形成我的应用程序的“模型”(原始后端数据转换为对象)。因此,我最终使用了 Object.create(从指定的原型创建新对象)和 对象. 分配(对象之间的复制属性)的组合。需要手动处理深度副本。我为此创建了 一个要点

有同样的问题,不想使用任何插件只是为了深度克隆:

static deepClone(object): any {
const cloneObj = (<any>object.constructor());
const attributes = Object.keys(object);
for (const attribute of attributes) {
const property = object[attribute];


if (typeof property === 'object') {
cloneObj[attribute] = this.deepClone(property);
} else {
cloneObj[attribute] = property;
}
}
return cloneObj;
}

编辑: 我使这个函数更具可读性,请检查其功能的异常如下

我已经创建了一个服务使用角度5或更高,它使用的 angular.copy()的基础 angularjs,它很适合我。此外,还有其他函数,如 isUndefined等。希望能有所帮助。 像任何优化一样,很高兴知道

import { Injectable } from '@angular/core';


@Injectable({providedIn: 'root'})
export class AngularService {


private TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
private stackSource = [];
private stackDest = [];


constructor() { }


public isNumber(value: any): boolean {
if ( typeof value === 'number' ) { return true; }
else { return false; }
}


public isTypedArray(value: any) {
return value && this.isNumber(value.length) && this.TYPED_ARRAY_REGEXP.test(toString.call(value));
}


public isArrayBuffer(obj: any) {
return toString.call(obj) === '[object ArrayBuffer]';
}


public isUndefined(value: any) {return typeof value === 'undefined'; }


public isObject(value: any) {  return value !== null && typeof value === 'object'; }


public isBlankObject(value: any) {
return value !== null && typeof value === 'object' && !Object.getPrototypeOf(value);
}


public isFunction(value: any) { return typeof value === 'function'; }


public setHashKey(obj: any, h: any) {
if (h) { obj.$$hashKey = h; }
else { delete obj.$$hashKey; }
}


private isWindow(obj: any) { return obj && obj.window === obj; }


private isScope(obj: any) { return obj && obj.$evalAsync && obj.$watch; }




private copyRecurse(source: any, destination: any) {


const h = destination.$$hashKey;


if (Array.isArray(source)) {
for (let i = 0, ii = source.length; i < ii; i++) {
destination.push(this.copyElement(source[i]));
}
} else if (this.isBlankObject(source)) {
for (const key of Object.keys(source)) {
destination[key] = this.copyElement(source[key]);
}
} else if (source && typeof source.hasOwnProperty === 'function') {
for (const key of Object.keys(source)) {
destination[key] = this.copyElement(source[key]);
}
} else {
for (const key of Object.keys(source)) {
destination[key] = this.copyElement(source[key]);
}
}
this.setHashKey(destination, h);
return destination;
}


private copyElement(source: any) {


if (!this.isObject(source)) {
return source;
}


const index = this.stackSource.indexOf(source);


if (index !== -1) {
return this.stackDest[index];
}


if (this.isWindow(source) || this.isScope(source)) {
throw console.log('Cant copy! Making copies of Window or Scope instances is not supported.');
}


let needsRecurse = false;
let destination = this.copyType(source);


if (destination === undefined) {
destination = Array.isArray(source) ? [] : Object.create(Object.getPrototypeOf(source));
needsRecurse = true;
}


this.stackSource.push(source);
this.stackDest.push(destination);


return needsRecurse
? this.copyRecurse(source, destination)
: destination;
}


private copyType = (source: any) => {


switch (toString.call(source)) {
case '[object Int8Array]':
case '[object Int16Array]':
case '[object Int32Array]':
case '[object Float32Array]':
case '[object Float64Array]':
case '[object Uint8Array]':
case '[object Uint8ClampedArray]':
case '[object Uint16Array]':
case '[object Uint32Array]':
return new source.constructor(this.copyElement(source.buffer), source.byteOffset, source.length);


case '[object ArrayBuffer]':
if (!source.slice) {
const copied = new ArrayBuffer(source.byteLength);
new Uint8Array(copied).set(new Uint8Array(source));
return copied;
}
return source.slice(0);


case '[object Boolean]':
case '[object Number]':
case '[object String]':
case '[object Date]':
return new source.constructor(source.valueOf());


case '[object RegExp]':
const re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
re.lastIndex = source.lastIndex;
return re;


case '[object Blob]':
return new source.constructor([source], {type: source.type});
}


if (this.isFunction(source.cloneNode)) {
return source.cloneNode(true);
}
}


public copy(source: any, destination?: any) {


if (destination) {
if (this.isTypedArray(destination) || this.isArrayBuffer(destination)) {
throw console.log('Cant copy! TypedArray destination cannot be mutated.');
}
if (source === destination) {
throw console.log('Cant copy! Source and destination are identical.');
}


if (Array.isArray(destination)) {
destination.length = 0;
} else {
destination.forEach((value: any, key: any) => {
if (key !== '$$hashKey') {
delete destination[key];
}
});
}


this.stackSource.push(source);
this.stackDest.push(destination);
return this.copyRecurse(source, destination);
}


return this.copyElement(source);
}
}

我和您一样面临着 angular.copy 和 angular.Expt 工作的问题,因为它们不会复制对象或创建对象,而不会添加一些依赖项。我的解决办法是:

  copyFactory = (() ->
resource = ->
resource.__super__.constructor.apply this, arguments
return
this.extendTo resource
resource
).call(factory)
let newObj = JSON.parse(JSON.stringify(obj))

JSON.stringify()方法将 JavaScript 对象或值转换为 JSON 字符串

您可以像下面这样克隆 Array

 this.assignCustomerList = Object.assign([], this.customerList);

然后复制这个对象

this.assignCustomer = Object.assign({}, this.customer);

如果您还没有使用 loash,我不建议仅仅为这一个方法安装它。相反,我建议建立一个更狭义的专业图书馆,比如“克隆”:

npm install clone

如果您愿意使用 npm 包,您可以尝试 “ ngx-scv-util”:

通过运行以下命令安装包:

npm i ngx-scv-util --save

使用以下方法将包导入到组件中:

import { NgxScvUtil } from "ngx-scv-util";
....
constructor(private util: NgxScvUtil) {}

用法:

let newObject = this.util.deepCopy(originalObject);

这是一个非常轻的软件包。更多信息可以在这里获得: https://www.npmjs.com/package/ngx-scv-util