2012-07-02 2 views
30

Можно создать дубликат:
What is the most efficient way to clone a JavaScript object?Javascript глубоко копирование объекта

У меня есть объект вроде этого:

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

и второй:

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

теперь я хочу, чтобы скопировать пользовательские значения пользователя User1 в пользователя, используя:

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

результат Пользователь будет:

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

USER.settings был полностью заменить в то время как я только хотел settings.second для замены.

Как достичь этого, не зная, сколько детского объекта имеет основной объект?

+2

Использование рекурсии? Вы искали глубокие функции Object.copy? – Bergi

+0

Можете ли вы использовать jQuery? –

+0

Из-за того, как javascript передает объекты вокруг (по ссылке), глубокое копирование вложенного объекта на самом деле является довольно серьезным испытанием. Я буду следовать совету Берги и найти уже существующий. –

ответ

14

Я обнаружил, что лучший путь состоит в следующем:

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); 

Что об этом?

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 устарел. Вы действительно должны использовать именованную функцию. Кроме того, вы забыли о hasOwnProperty, что очень важно. – Bergi

+0

посмотреть обновление, лучше? –

+0

Да, хотя вы все еще копируете свойства прототипа. И копирование к целевому объекту действительно должно называться «расширяться», а не «клонировать» («deepextend» с вашей первой попытки будет еще лучше) – Bergi

-1

Это действительно взломанный, но это должно сработать. Я предлагаю сделать, как другие пользователи предложили в комментариях; найдите уже существующую библиотеку, которая сделает это за вас.

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

объект, который я разместил, был примером, я ищу что-то, что будет работать везде –

+1

O ok. Хорошо, я бы посмотрел на jQuerys http://api.jquery.com/jQuery.extend/, похоже, что он может делать именно то, что вы ищете. –

+0

Я нашел это, похоже, работает (не идеально, но в начале) http://my.opera.com/GreyWyvern/blog/show.dml/1725165, для jquery Я хотел бы kkep его фреймворк agnostic –

4

Приобретенный метод расширения jQuery и сделал его агностиком.

Gist: Library agnostic version of jQuery's Extend

Его завернутые в конструкторе Extender, так что вам не придется инстанцирует все свои внутренние методы каждый раз, когда вы вызываете метод расширения.

Отказ от ответственности: Я не проверял это широко. Это в основном 1: 1 клон расширения jQuery(), однако ваш пробег может отличаться.

Используйте его следующим образом.

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

Это может быть более длинным, чем другие но он работает надежно и работает как с массивами, так и с объектами. Спасибо! –

+0

Это помогло мне в носороге .. cheers –

Смежные вопросы