2012-07-02 47 views
30

thể trùng lặp:
What is the most efficient way to clone a JavaScript object?Javascript đối tượng sao chép sâu

tôi có một đối tượng như thế này:

User = {  
    name: "user", 
    settings: { 
    first: "1", 
    second: "2"  
    }  
} 

và thứ hai:

user1 = { 
    name: "user1", 
    settings: { 
    second: "3" 
    } 
} 

bây giờ tôi muốn sao chép giá trị tùy chỉnh user1 của thành tài khoản, sử dụng:

for(var key in user1){ 
     User[key] = user1[key]; 
    } 

kết quả tài sẽ là:

User = { 
    name: "user1", 
    settings: { 
    second: "3" 
    } 
} 

User.settings đã hoàn toàn thay thế trong khi tôi muốn chỉ settings.second được thay thế.

Làm thế nào để đạt được điều này, mà không biết có bao nhiêu đối tượng con đối tượng chính có?

+2

Sử dụng đệ quy? Bạn đã tìm kiếm các hàm Object.copy sâu chưa? – Bergi

+0

Bạn có thể sử dụng jQuery không? –

+0

Vì javascript truyền các đối tượng xung quanh như thế nào (bằng cách tham chiếu), việc sao chép sâu một đối tượng lồng nhau thực sự là một thử thách. Tôi sẽ làm theo lời khuyên của @ Bergi và tìm một lời khuyên từ trước. –

Trả lời

14

tôi đã tìm thấy rằng cách tốt nhất để đi là thế này:

http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/

Object.deepExtend = function(destination, source) { 
    for (var property in source) { 
    if (typeof source[property] === "object" && 
    source[property] !== null) { 
     destination[property] = destination[property] || {}; 
     arguments.callee(destination[property], source[property]); 
    } else { 
     destination[property] = source[property]; 
    } 
    } 
    return destination; 
}; 


Object.extend(destination, source); 

gì về điều này?

function clone(destination, source) { 
     for (var property in source) { 
      if (typeof source[property] === "object" && source[property] !== null && destination[property]) { 
       clone(destination[property], source[property]); 
      } else { 
       destination[property] = source[property]; 
      } 
     } 
    }; 
+1

arguments.callee không được chấp nhận. Bạn thực sự nên sử dụng một hàm được đặt tên. Ngoài ra, bạn đã quên hasOwnProperty khá quan trọng. – Bergi

+0

xem bản cập nhật, có tốt hơn không? –

+0

Có, mặc dù bạn vẫn sao chép các thuộc tính từ nguyên mẫu. Và sao chép vào một đối tượng đích thực sự nên được gọi là "mở rộng", không phải "nhân bản" ("deepextend" từ lần thử đầu tiên của bạn sẽ tốt hơn) – Bergi

-1

Điều này thực sự rất khó, nhưng điều này sẽ hiệu quả. Tôi khuyên bạn nên làm như những người dùng khác đã đề xuất trong các ý kiến; tìm một thư viện đã tồn tại từ trước sẽ thực hiện việc này cho bạn.

for(var key in user1){ 
    var temp = User[key] 
    User[key] = user1[key]; 
    for(var key1 in temp){ 
     if(User[key][key1] == null){ 
     User[key][key1] = temp[key1]; 
     } 
    } 
} 
+0

đối tượng tôi đăng là một ví dụ tôi đang tìm kiếm thứ gì đó sẽ hoạt động ở mọi nơi –

+1

O ok. Vâng, tôi sẽ xem xét jQuerys http://api.jquery.com/jQuery.extend/, có vẻ như nó có thể làm chính xác những gì bạn đang tìm kiếm. –

+0

Tôi đã tìm thấy điều này dường như đang hoạt động (không hoàn hảo nhưng bắt đầu) http://my.opera.com/GreyWyvern/blog/show.dml/1725165, cho jquery Tôi muốn kkep nó khuôn khổ bất khả tri –

4

Đã lấy phương pháp mở rộng của jQuery và làm cho thư viện trở nên bất khả tri.

Gist: Library agnostic version of jQuery's Extend

của nó được bọc trong một constructor Extender, vì vậy bạn không cần phải nhanh chóng tất cả các phương pháp nội bộ của mình mỗi lần bạn gọi mở rộng phương pháp.

Tuyên bố từ chối trách nhiệm: Tôi chưa thử nghiệm rộng rãi. Về cơ bản nó là bản sao 1: 1 của mở rộng jQuery(), tuy nhiên số dặm của bạn có thể thay đổi.

Sử dụng nó như thế này.

var user1 = { 
    name: "user1", 
    settings: { 
    first: "1", 
     second: {bar: 'foo'} 
    } 
}; 
var user2 = { 
    name: "user2", 
    settings: { 
    second: {foo:'bar'} 
    } 
}; 

/* merge user1 into User */ 
__extend(true, user1, user2); 

// Modifies the User object 
user1.settings.second.foo == 'bar'; // true 

// note, you can do assignment too. 
var newUser = __extend(true, user1, user2); 

See here for more documentation

+0

Điều này có thể dài hơn các giới hạn khác các giải pháp nhưng nó hoạt động đáng tin cậy và hoạt động trên cả hai loại mảng và đối tượng. Cảm ơn bạn! –

+0

Điều này đã giúp tôi trong tê giác .. cổ vũ –

Các vấn đề liên quan