Питання Як правильно клонувати об'єкт JavaScript?


У мене є об'єкт x. Я хотів би скопіювати його як об'єкт y, такий, що змінюється на y не змінюйте x. Я зрозумів, що копіювання об'єктів, отриманих з вбудованих об'єктів JavaScript, призведе до додаткових, небажаних властивостей. Це не проблема, оскільки я копіюю один з моїх власних, літерально побудованих об'єктів.

Як правильно клонувати об'єкт JavaScript?


2403


походження


Подивіться на це питання: stackoverflow.com/questions/122102/... - Niyaz
Для JSON я використовую mObj=JSON.parse(JSON.stringify(jsonObject)); - Lord Loh.
Я дійсно не розумію, чому ніхто не пропонує Object.create(o), це робить все, що запитує автор? - froginvasion
var x = { deep: { key: 1 } }; var y = Object.create(x); x.deep.key = 2;  Після цього y.deep.key буде також 2, отже Object.create НЕ МОЖУТЬ використовуватися для клонування ... - Ruben Stolk
@ r3wt, що не буде працювати ... Будь ласка, публікуйте лише після виконання базової перевірки рішення .. - akshay


Відповіді:


Оновлений відповідь

Просто використовуй Object.assign () як це було запропоновано тут

Але пам'ятайте, що це робить лише невелику копію. Вкладені об'єкти як і раніше копіюються як посилання.


Застаріла відповідь

Для цього будь-який об'єкт у JavaScript не буде простим чи простим. Ви зіткнетеся з проблемою помилкового збору атрибутів з прототипу об'єкта, який слід залишити у прототипі та не копіювати в новий екземпляр. Якщо, наприклад, ви додаєте clone метод до Object.prototype, як показують деякі відповіді, вам потрібно буде явно пропустити цей атрибут. Але що робити, якщо до цього додані інші додаткові методи Object.prototype, або інші проміжні прототипи, про які ви не знаєте? У такому випадку ви копіюєте атрибути, які вам не слід, тому вам потрібно виявити непередбачені, не локальні атрибути з hasOwnProperty метод

Окрім неперерахованих атрибутів, ви зіткнетеся з більш жорсткою проблемою при спробі копіювати об'єкти, які мають приховані властивості. Наприклад, prototype є прихованою властивістю функції. Також до прототипу об'єкта посилається атрибут __proto__, який також приховується, і не буде скопійовано циклом / in циклу, що повторюється над атрибутами вихідного об'єкта. Я думаю __proto__ може бути специфічним для інтерфейсу JavaScript в Firefox, і це може бути щось інше в інших браузерах, але ви отримаєте картинку. Не все перелічене. Ви можете скопіювати прихований атрибут, якщо ви знаєте його ім'я, але я не знаю, як це автоматично відкрити.

Ще одним кроком у пошуках елегантного рішення є проблема правильного встановлення спадщини прототипу. Якщо є ваш прототип вихідного об'єкта Object, то просто створення нового загального об'єкта з {} буде працювати, але якщо прототип джерела є нащадком Object, то ви будете позбавлені додаткових членів з того прототипу, який ви пропустили за допомогою hasOwnProperty фільтр або які були в прототипі, але не були перераховані в першу чергу. Одним із рішень може бути виклик вихідного об'єкта constructor властивість отримати об'єкт початкової копії, а потім скопіювати атрибути, але тоді ви все одно не отримаєте атрибути, які не можуть бути перелічені. Наприклад, a Date об'єкт зберігає свої дані як прихований елемент:

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

var d1 = new Date();

/* Executes function after 5 seconds. */
setTimeout(function(){
    var d2 = clone(d1);
    alert("d1 = " + d1.toString() + "\nd2 = " + d2.toString());
}, 5000);

Строк дати для d1 буде на 5 секунд позаду d2. Спосіб зробити це Date те ж саме, що інше, - це викликати setTime метод, але це специфічно для Date клас Я не думаю, що є загальним рішенням цієї проблеми, хоча я був би раді помилятися!

Коли мені довелося здійснити загальне глибоке копіювання, я опинився на компромісній основі, вважаючи, що мені потрібно буде просто скопіювати просту Object, Array, Date, String, Number, або Boolean. Останні три типи незмінними, тому я міг виконувати мізерну копію і не турбуватися про зміну. Далі я припустив, що будь-які елементи, що містяться в Object або Array також буде одним із шести простих типів у цьому списку. Це можна виконати за допомогою коду:

function clone(obj) {
    var copy;

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

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

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

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

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

Вищезазначена функція буде працювати адекватно для 6 простих типів, про які я згадав, якщо дані в об'єктах та масивах утворюють деревоподібну структуру. Тобто існує не більше однієї посилання на ті ж дані в об'єкті. Наприклад:

// This would be cloneable:
var tree = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "right" : null,
    "data"  : 8
};

// This would kind-of work, but you would get 2 copies of the 
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];

// Cloning this would cause a stack overflow due to infinite recursion:
var cyclicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
cyclicGraph["right"] = cyclicGraph;

Вона не зможе обробляти будь-який об'єкт JavaScript, але це може бути достатньо для багатьох цілей, якщо ви не вважаєте, що він буде працювати тільки на те, що ви кидаєте на нього.


1313



майже добре працював в nodejs - просто потрібно було змінити рядок для (var i = 0, var len = obj.length; i <len; ++ i) {to for (var i = 0; i <obj.length; + + i) { - Trindaz
Для майбутніх Googlers: така ж глибока копія, передаючи посилання рекурсивно замість використання операторів "return" на gist.github.com/2234277 - Trindaz
Буде сьогодні JSON.parse(JSON.stringify([some object]),[some revirer function]) бути рішенням? - KooiInc
У першому фрагменті ви впевнені, що це не повинно бути var cpy = new obj.constructor()? - cyon
Призначення об'єкту, схоже, не створює справжню копію в Chrome, зберігає посилання на оригінальний об'єкт - в кінцевому підсумку використовується JSON.stringify і JSON.parse для клонування - чудово працює - 1owk3y


З jQuery ви можете дрібна копія з продовжити:

var copiedObject = jQuery.extend({}, originalObject)

подальші зміни до скопійованого об'єкта не впливатимуть на вихідний об'єкт, і навпаки.

Або зробити глибока копія:

var copiedObject = jQuery.extend(true, {}, originalObject)

713



або навіть: var copiedObject = jQuery.extend({},originalObject); - Grant McLean
Також корисно вказати true як перший параметр для глибокої копії: jQuery.extend(true, {}, originalObject); - Will Shaver
Так, я знайшов цю посилання корисною (таке ж рішення як Pascal) stackoverflow.com/questions/122102/... - Garry English
@Will Shaver - ТАК! Це воно! Без варіанту глибокого копіювання це не спрацювало для мене! - thorinkor
Просто зауваження, це не копіює Прото конструктор оригінального об'єкта - Sam Jones


Якщо ви не використовуєте функції у вашому об'єкті, дуже простий лайнер може бути таким:

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

Це працює для всіх видів об'єктів, що містять об'єкти, масиви, рядки, булеви і цифри.

Дивись також ця стаття про алгоритм структурованого клонування браузерів який використовується при надсиланні повідомлень працівникам та від них. Він також містить функцію глибокого клонування.


691



Зауважте, що це можна використовувати лише для тестування. По-перше, далеко не оптимальний спосіб використання часу та пам'яті. По-друге, не всі браузери мають такі методи. - Nux
@Nux, чому б не оптимальний з точки зору часу та пам'яті? Міян пише: "Причина, чому цей метод є повільним, ніж мізерне копіювання (на глибокому об'єкті), полягає в тому, що цей метод, за визначенням, являє собою глибокі копії. Але оскільки JSON реалізується у власному коді (у більшості браузерів), це буде значно швидше ніж за допомогою будь-якого іншого рішення для глибокого копіювання на основі JavaScript, і іноді може бути швидшим, ніж методика мелкого копіювання на базі JavaScript (див. jsperf.com/cloning-an-object/79). " stackoverflow.com/questions/122102/... - BeauCielBleu
Я просто хочу додати оновлення до цього жовтня 2014 року. Chrome 37+ швидше за допомогою JSON.parse (JSON.stringify (oldObject)); Перевага використання цього полягає в тому, що для движку javascript дуже легко побачити та оптимізувати щось краще, якщо воно хоче. - mirhagk
Це буде дерьмо по всьому JSON, якщо об'єкт має не-stringify-здатні речі, такі як Нескінченність, невизначеноі т. д. Спробуйте цей об'єкт: a = { b: Infinity, c: undefined } - kumar_harsh
Оновлення 2016 року: Це повинно тепер працювати практично в кожному браузері, який широко використовується. (побачити Чи можу я використовувати ...) Головне питання зараз буде, чи є воно достатньо продуктивним. - James Foster


У ECMAScript 6 є Об'єкт.присвоєння метод, котрий копіює значення всіх перелічених власних властивостей від одного об'єкта до іншого. Наприклад:

var x = {myProp: "value"};
var y = Object.assign({}, x); 

Але пам'ятайте, що вкладені об'єкти як і раніше копіюються як посилання.


509



Так, я вірю в це Object.assign це шлях. Це також легко заповнити: gist.github.com/rafaelrinaldi/43813e707970bd2d77fa - Rafael
Але пам'ятайте, що це робить лише невелику копію. Вкладені об'єкти до цих пір копіюються як посилання! - ohager
Також слід пам'ятати, що це буде копіювати над "методами", визначеними через об'єктні літерали (оскільки ці є перелічені) але ні методи відрізнені за допомогою "класу" механізму (оскільки ці ні перераховано) - Marcus Junius Brutus
Я думаю, слід згадати, що це не підтримується IE, крім Edge. Деякі люди все ще використовують це. - Saulius
Це таке ж, як @EugeneTiurin його відповідь. - Wilt


Є багато відповідей, але ніхто не згадує Object.create з ECMAScript 5, який за загальним визнанням не дає точної копії, але встановлює джерело як прототип нового об'єкта.

Таким чином, це не точна відповідь на питання, але це рішення в одній лінії і, таким чином, елегантне. І це найкраще працює для 2 випадків:

  1. Там, де таке успадкування корисно (дух!)
  2. Там, де вихідний об'єкт не буде модифікований, таким чином зробивши зв'язок між 2 об'єктами невипуск.

Приклад:

var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - prototype changed
bar.a = 3;
foo.a; // Still 2, since setting bar.a makes it an "own" property

Чому я вважаю це рішення кращим? Це рідний, таким чином, не циклу, ні рекурсії. Однак, для старих веб-переглядачів буде потрібно поліфільм.


114



Примітка: Object.create - це не глибока копія (вона згадала не рекурсії). Доказ: var a = {b:'hello',c:{d:'world'}}, b = Object.create(a); a == b /* false */; a.c == b.c /* true */; - zamnuts
Це прототипна спадщина, а не клонування. Це абсолютно різні речі. Новий об'єкт не має власних властивостей, він просто вказує на властивості прототипу. Точка клонування - створити новий новий об'єкт, який не посилається на властивості іншого об'єкта. - d13
Я повністю згоден з вами. Я також погоджуюсь з тим, що це не клонування, яке може бути "призначеним". Але прийдіть на людей, обіймайте природу JavaScript замість того, щоб намагатися знайти незрозумілі рішення, які не стандартизовані. Звичайно, вам не подобаються прототипи, і вони всі "бла" для вас, але вони насправді дуже корисні, якщо ви знаєте, що ви робите. - froginvasion
@RobG: ця стаття пояснює різницю між посиланнями та клонуваннями: en.wikipedia.org/wiki/Cloning_(programming). Object.create вказує на властивості батьків через посилання. Це означає, що зміна властивостей батьків змінюється, і дитина змінить також. У цьому є деякі несподівані побічні ефекти з вставленими масивами та об'єктами, які можуть призвести до важко знайти помилки у вашому коді, якщо ви не знаєте про них: jsbin.com/EKivInO/2. Клонований об'єкт - це зовсім новий, незалежний об'єкт, який має ті самі властивості та значення, що і батьківський, але не пов'язаний з батьком. - d13
Це обманює людей ... Object.create () може бути використаний як засіб наслідування, але клонування недалеко від нього. - prajnavantha


Елегантний спосіб клонувати об'єкт Javascript в одному рядку коду

Ан Object.assign Метод є частиною стандарту ECMAScript 2015 (ES6) і робить саме те, що вам потрібно.

var clone = Object.assign({}, obj);

Метод Object.assign () використовується для копіювання значень усіх перелітних власних властивостей з одного або декількох вихідних об'єктів до цільового об'єкта.

Читати далі ...

The поліфіль для підтримки старих веб-переглядачів:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}

105



Вибачте за німе питання, але чому Object.assign приймати два параметри, коли value функція у поліфайлі займає лише один параметр? - Qwertie
@Qwertie вчора Всі аргументи повторюються і об'єднуються в один об'єкт, визначаючи пріоритет властивостей з останнього пройденого аргументу - Eugene Tiurin
О, я бачу, спасибі (я не був знайомий з arguments об'єкт раніше.) У мене проблеми з пошуком Object() через Google ... це тип, чи не так? - Qwertie
це буде виконувати тільки дрібне "клонування" - Marcus Junius Brutus


За MDN:

  • Якщо ви хочете неглибокі копії, скористайтеся Object.assign({}, a)
  • Для "глибокої" копії використовуйте JSON.parse(JSON.stringify(a))

Немає потреби в зовнішніх бібліотеках, але потрібно перевірити спочатку сумісність браузера.


105



JSON.parse (JSON.stringify (a)) виглядає красиво, але перед використанням я рекомендую провести тестування часу, необхідного для потрібної колекції. Залежно від розміру об'єкта це не може бути найшвидшим варіантом. - Edza
Я зауважив метод JSON, який перетворює об'єкти дати в рядки, але не в дату. Потрібно мати справу з веселими часовими зонами в Javascript і вручну виправити будь-які дати. Можливі подібні випадки для інших типів, крім дат - Steve Seeger
для дати, я б міг використовувати moment.js з моменту його створення clone функціональність. дивіться більше тут momentjs.com/docs/#/parsing/moment-clone - Tareq


Якщо ви в порядку з неглибокою копією, в бібліотеці underscore.js є клон метод

y = _.clone(x);

або ви можете розширити його як

copiedObject = _.extend({},originalObject);

70



І логас має cloneDeep - dule
Дякую. Використання цієї техніки на сервері Метеор. - Turbo
Мерчі людина! що зробило роботу для мене божевільною, що я використовував це через деякий час. застряг у проекті VUE, наскільки я знаю, VUE не має вбудованої функції для клонування об'єкта, такого як кутовий має (angular.copy) - Arnaud Bouchot


Існує кілька проблем, пов'язаних з більшістю рішень в Інтернеті. Тому я вирішив зробити подальше спостереження, яке включає, чому прийнята відповідь не повинна бути прийнята.

початкова ситуація

я хочу глибока копія Javascript Object з усіма своїми дітьми та їхніми дітьми тощо. Але оскільки я не якийсь нормальний розробник, моя Object мав нормальний  properties, circular structures і навіть nested objects.

Тож давайте створимо a circular structure і a nested object перший.

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

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

Давайте об'єднати все в одному Object названий a.

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

Далі ми хочемо копіювати a в змінну з ім'ям b і мутуєш це.

var b = a;

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

Ви знаєте, що тут сталося, тому що якщо б ви не потрапили б навіть на це велике питання.

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"
    }
}

Тепер давайте знайдемо рішення.

JSON

Перша спроба, яку я намагався використати JSON.

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

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

Не витрачайте на нього багато часу, ви отримаєте TypeError: Converting circular structure to JSON.

Рекурсивна копія (прийнята "відповідь")

Давайте поглянемо на прийняту відповідь.

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.");
}

Виглядає добре, гей? Це рекурсивна копія об'єкта та обробляє інші типи, наприклад Date, але це не було вимогою.

var b = cloneSO(a);

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

Рекурсія і circular structures не працює добре ... RangeError: Maximum call stack size exceeded

нативне рішення

Після сперечатися з моїм співробітником, мій бос запитав нас про те, що сталося, і він знайшов простий рішення після деякого гуглювання. Це називається Object.create.

var b = Object.create(a);

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

Це рішення було додано до Javascript деякий час тому і навіть обробляється circular structure.

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"
    }
}

... і ви бачите, це не спрацювало з вкладеної структурою всередині.

поліфіль для рідного розчину

Для цього є поліфільм Object.create у старшому браузері так само, як і в IE 8. Це щось на зразок рекомендованого Mozilla, і, звичайно, це не ідеальне рішення і призводить до тієї ж проблеми, що й нативне рішення.

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

var b = clonePF(a);

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

Я поставив F за межами сфери, тому ми можемо подивитися на що instanceof розповідає нам.

console.log(a, b);

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

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

console.log(typeof a, typeof b);

a --> object
b --> object

console.log(a instanceof Object, b instanceof Object);

a --> true
b --> true

console.log(a instanceof F, b instanceof F);

a --> false
b --> true

Те ж проблема, що і в нативне рішення, але трохи гірший вихід.

краще (але не досконале) рішення

Коли копатись, я знайшов подібне запитання (У Javascript при виконанні глибокої копії, як уникнути циклу через властивість "це"?) до цього, але з кращим рішенням.

function cloneDR(o) {
    const gdcc = "__getDeepCircularCopy__";
    if (o !== Object(o)) {
        return o; // primitive value
    }

    var set = gdcc in o,
        cache = o[gdcc],
        result;
    if (set && typeof cache == "function") {
        return cache();
    }
    // else
    o[gdcc] = function() { return result; }; // overwrite
    if (o instanceof Array) {
        result = [];
        for (var i=0; i<o.length; i++) {
            result[i] = cloneDR(o[i]);
        }
    } else {
        result = {};
        for (var prop in o)
            if (prop != gdcc)
                result[prop] = cloneDR(o[prop]);
            else if (set)
                result[prop] = cloneDR(cache);
    }
    if (set) {
        o[gdcc] = cache; // reset
    } else {
        delete o[gdcc]; // unset again
    }
    return result;
}

var b = cloneDR(a);

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

І давайте поглянемо на вихід ...

console.log(a, b);

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

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

console.log(typeof a, typeof b);

a --> object
b --> object

console.log(a instanceof Object, b instanceof Object);

a --> true
b --> true

console.log(a instanceof F, b instanceof F);

a --> false
b --> false

Ці вимоги співпадають, але існують ще деякі менші проблеми, включаючи зміну instance від nested і circ до Object.

Структура дерев, що поділяють лист, не буде скопійована, вони стануть двома незалежними листами:

        [Object]                     [Object]
         /    \                       /    \
        /      \                     /      \
      |/_      _\|                 |/_      _\|  
  [Object]    [Object]   ===>  [Object]    [Object]
       \        /                 |           |
        \      /                  |           |
        _\|  |/_                 \|/         \|/
        [Object]               [Object]    [Object]

висновок

Останнє рішення, яке використовує рекурсію та кеш, може бути не найкращим, але це а реальний глибока копія об'єкта. Він обробляє прості properties, circular structures і nested object, але це буде збити примірник їх під час клонування.

http://jsfiddle.net/einfallstoll/N4mr2/


63



так що змову полягає в тому, щоб уникнути цієї проблеми :) - mikus
@mikus, поки там немає реальний специфікація, яка охоплює більше, ніж просто основні випадки використання, так. - Fabio Poloni
Добрий аналіз запропонованих вище рішень, але висновок, зроблений автором, вказує на те, що цього питання не вирішено. - Amir Mog
Смутно, що JS не включає в себе функції власної клони. - l00k
Серед усіх найпопулярніших відповідей, я відчуваю, що це близько до правильного. - KTU


Одним з особливо неелегантних рішень є використання кодування JSON для створення глибоких копій об'єктів, які не мають методів учасників. Методологія JSON кодує ваш цільовий об'єкт, після чого, розшифруючи його, ви отримуєте копію, яку ви шукаєте. Ви можете декодувати стільки разів, скільки хочете зробити стільки копій, скільки вам потрібно.

Звичайно, функції не належать до JSON, тому це працює тільки для об'єктів без методів учасників.

Ця методологія була ідеальною для мого випадку використання, оскільки я зберігаю кольорові JSON у магазині ключових значень, і коли вони виставляються як об'єкти в JavaScript API, кожен об'єкт насправді містить копію оригінального стану об'єкта, тому ми може обчислити дельту після того, як абонент здійснив мутацію виявленого об'єкта.

var object1 = {key:"value"};
var object2 = object1;

object2 = JSON.stringify(object1);
object2 = JSON.parse(object2);

object2.key = "a change";
console.log(object1);// returns value

36



Чому функції не належать до JSON? Я бачив, що їх передано як JSON більше одного разу ... - the_drow
Функції не є частиною специфікації JSON, тому що вони не є захищеним (або розумним) способом перенесення даних, що саме було створено для JSON. Я знаю, що корінець JSON у Firefox просто ігнорує передані йому функції, але я не впевнений в поведінці інших. - Kris Walker
ІМХО найкраща відповідь, тому що О.П. стверджує "буквально побудовані" об'єкти - mark
Немає нічого більш невловимого, ніж використання слова unelegant. - Kevin Laity
@ mark: { 'foo': function() { return 1; } } це буквально побудований об'єкт. - abarnert