Hướng dẫn how do you copy an object in javascript? - làm thế nào để bạn sao chép một đối tượng trong javascript?

Có một số vấn đề với hầu hết các giải pháp trên Internet. Vì vậy, tôi quyết định thực hiện theo dõi, bao gồm, tại sao câu trả lời được chấp nhận không nên được chấp nhận.

bắt đầu tình huống

Tôi muốn kết hợp sâu sắc một JavaScript

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4 với tất cả trẻ em và con cái của họ, v.v. Nhưng vì tôi không phải là nhà phát triển bình thường,
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4 của tôi có bình thường
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
6,
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
7 và thậm chí
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
8.deep-copy a Javascript
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4 with all of its children and their children and so on. But since I'm not kind of a normal developer, my
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4 has normal
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
6,
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
7 and even
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
8.

Vì vậy, hãy tạo một

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
9 và
var b = a;

b.x = 'b';
b.nested.y = 'b';
0 trước.

function Circ() {
    this.me = this;
}

function Nested(y) {
    this.y = y;
}

Hãy mang mọi thứ lại với nhau trong một

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4 có tên
var b = a;

b.x = 'b';
b.nested.y = 'b';
2.

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};

Tiếp theo, chúng tôi muốn sao chép

var b = a;

b.x = 'b';
b.nested.y = 'b';
2 vào một biến có tên
var b = a;

b.x = 'b';
b.nested.y = 'b';
4 và biến đổi nó.

var b = a;

b.x = 'b';
b.nested.y = 'b';

Bạn biết những gì đã xảy ra ở đây bởi vì nếu không bạn thậm chí sẽ không đáp ứng câu hỏi tuyệt vời này.

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

Bây giờ chúng ta hãy tìm một giải pháp.

Json

Nỗ lực đầu tiên tôi đã thử là sử dụng

var b = a;

b.x = 'b';
b.nested.y = 'b';
5.

var b = JSON.parse( JSON.stringify( a ) );

b.x = 'b';
b.nested.y = 'b';

Đừng lãng phí quá nhiều thời gian cho nó, bạn sẽ nhận được

var b = a;

b.x = 'b';
b.nested.y = 'b';
6.

Bản sao đệ quy ("câu trả lời" được chấp nhận

Chúng ta hãy xem câu trả lời được chấp nhận.

function cloneSO(obj) {
    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = cloneSO(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

Có vẻ tốt, heh? Đó là một bản sao đệ quy của đối tượng và cũng xử lý các loại khác, như

var b = a;

b.x = 'b';
b.nested.y = 'b';
7, nhưng đó không phải là một yêu cầu.

var b = cloneSO(a);

b.x = 'b';
b.nested.y = 'b';

Đệ quy và

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
7 không hoạt động tốt với nhau ...
var b = a;

b.x = 'b';
b.nested.y = 'b';
9

Giải pháp gốc

Sau khi tranh cãi với đồng nghiệp của tôi, ông chủ của tôi đã hỏi chúng tôi chuyện gì đã xảy ra, và anh ấy đã tìm thấy một giải pháp đơn giản sau một số googling. Nó được gọi là

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
0.

var b = Object.create(a);

b.x = 'b';
b.nested.y = 'b';

Giải pháp này đã được thêm vào JavaScript một thời gian trước và thậm chí xử lý

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
9.

console.log(a, b);

a --> Object {
    x: "a",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

... Và bạn thấy đấy, nó không hoạt động với cấu trúc lồng nhau bên trong.

polyfill cho giải pháp gốc

Có một polyfill cho

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
0 trong trình duyệt cũ giống như IE 8. Nó giống như một cái gì đó được đề xuất bởi Mozilla, và tất nhiên, nó không hoàn hảo và dẫn đến vấn đề tương tự như giải pháp gốc.

function F() {};
function clonePF(o) {
    F.prototype = o;
    return new F();
}

var b = clonePF(a);

b.x = 'b';
b.nested.y = 'b';

Tôi đã đặt

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
3 ngoài phạm vi để chúng ta có thể xem xét những gì
console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
4 nói với chúng ta.

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
0

Vấn đề tương tự như giải pháp gốc, nhưng đầu ra tồi tệ hơn một chút.

Giải pháp tốt hơn (nhưng không hoàn hảo)

Khi đào xung quanh, tôi tìm thấy một câu hỏi tương tự (trong JavaScript, khi thực hiện một bản sao sâu, làm thế nào để tôi tránh một chu kỳ, do một tài sản là "cái này"?) Cho cái này, nhưng với một giải pháp tốt hơn.

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
1

Và chúng ta hãy xem đầu ra ...

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
2

Các yêu cầu được khớp, nhưng vẫn còn một số vấn đề nhỏ hơn, bao gồm thay đổi

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
5 của
console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
6 và
console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
7 thành
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
4.

Cấu trúc của những cây có chung một chiếc lá sẽ không được sao chép, chúng sẽ trở thành hai lá độc lập:

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
3

phần kết luận

Giải pháp cuối cùng sử dụng đệ quy và bộ nhớ cache, có thể không phải là tốt nhất, nhưng đó là một bản sao sâu thực sự của đối tượng. Nó xử lý đơn giản

var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
6,
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
7 và
var b = a;

b.x = 'b';
b.nested.y = 'b';
0, nhưng nó sẽ làm rối loạn chúng trong khi nhân bản.real deep-copy of the object. It handles simple
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
6,
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
7 and
var b = a;

b.x = 'b';
b.nested.y = 'b';
0, but it will mess up the instance of them while cloning.

JSfiddle

Bạn có thể sao chép một đối tượng?

Có một số cách để sao chép một đối tượng, phổ biến nhất là một hàm tạo sao chép hoặc nhân bản. Sao chép được thực hiện chủ yếu để bản sao có thể được sửa đổi hoặc di chuyển, hoặc giá trị hiện tại được bảo tồn. Nếu một trong hai điều này không cần thiết, một tham chiếu đến dữ liệu gốc là đủ và hiệu quả hơn, vì không có sao chép xảy ra.. Copying is done mostly so the copy can be modified or moved, or the current value preserved. If either of these is unneeded, a reference to the original data is sufficient and more efficient, as no copying occurs.

Toán tử nào được sử dụng để sao chép một đối tượng trong JavaScript?

Phương thức gán (). Đối tượng. Phương thức gán () được sử dụng để sao chép các giá trị của tất cả các thuộc tính riêng từ một hoặc nhiều đối tượng nguồn sang đối tượng đích. method. The Object. assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

JavaScript có thể sao chép đối tượng bằng tài liệu tham khảo không?

Chuyển các biến cho các hàm đang hoạt động giống như cách sao chép cho cùng loại dữ liệu trong hầu hết các ngôn ngữ.Trong các loại nguyên thủy JavaScript được sao chép và truyền bởi giá trị và các đối tượng được sao chép và truyền bởi giá trị tham chiếu.objects are copied and passed by reference value.

Làm thế nào để bạn gán một đối tượng cho một đối tượng khác trong JavaScript?

Demo javaScript: object.assign ()..
const Target = {a: 1, b: 2} ;.
const nguồn = {b: 4, c: 5} ;.
const returnedTarget = object.gán (mục tiêu, nguồn) ;.
Bảng điều khiển.Nhật ký (mục tiêu) ;.
Bảng điều khiển.log (returnedTarget === Target) ;.