Подтвердить что ты не робот

Родной способ слияния объектов в Javascript

Объект Javascript не имеет никакой операции слияния. Если у вас есть два объекта, скажите

{a:1, b:2}
{c:3, d:4}

И хочу получить

{a:1, b:2, c:3, d:4}

Насколько я знаю, вам нужно перебирать объекты. То есть вы решаете либо стратегию слияния влево, либо стратегию слияния, а затем вы делаете что-то вроде (упрощенного)

for (key in object2) {
  object1[key] = object2[key];
}

Это нормально. Однако Javascript имеет функцию call и prototype. Например, поворот arguments в Array можно сделать с помощью

Array.prototype.slice.call(arguments)

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

Вопрос

Есть ли уловка для использования этого шаблона прототипа/вызова, возможно, для функций обхода Attribute или Node объекта DOM или, возможно, некоторых из общих String функций, чтобы выполнить слияние собственных объектов?

Код выглядит примерно так:

var merged = somethingrandom.obscuremethod.call(object1, object2)

И в результате вы получите собственное слияние без обхода.

Возможное, субоптимальное решение

Если вы можете использовать свойство constructor для Object, а затем принудить один объект к созданию конструктора другого объекта, а затем запустить new над составным объектом, вы можете получить слияние бесплатно. Но у меня нет четкого понимания всех последствий функции constructor в javascript для выполнения этого вызова.

Лемма

Тот же вопрос справедлив для Arrays. Общая проблема состоит в том, чтобы взять, например, 7 массивов чисел, а затем попытаться выяснить пересечение этих массивов. То есть, какие числа существуют во всех 7 массивах.

Вы могли бы объединить их вместе, затем сделать вид, а затем сделать обход, конечно. Но было бы неплохо, если бы где-то было пересечено какое-то общее пересечение, которое мы можем принудить массив к выполнению изначально.

Любые мысли?

изменить:

На полпути туда

Для проблемы с массивом вы можете сделать следующее:

array.concat(a, b, c).sort(). join (':'), а затем используйте некоторые сложные шаблоны захвата и повтора RegExp, чтобы пройти. Реализация RegExp, если вы не знаете, запускается на очень простой виртуальной машине на основе стека. Когда вы инициализируете свое регулярное выражение, которое действительно является компиляцией программы (RegExp.compile - это устаревший метод JS). Тогда нативный пробегает строку по-быстрому. Возможно, вы можете использовать это для порогов членства и получить лучшую производительность...

Он все еще не проходит весь путь.

4b9b3361

Ответ 1

Мой ответ на это будет разочаровывающим, но все же:

нет

не

Причина для этого проста: реализация проекта Resig слияния (или "расширение", поскольку она вызвала объекты) в jQuery делает цикл, точно такой же, как в вашем вопросе. Вы можете посмотреть здесь здесь. И я смею сказать, что если Джон Ресиг не найдет умного встроенного способа сделать это, то простые смертные из stackoverflow не будут:)

Ответ 2

Вопрос в миллион долларов! Я пробовал делать это по-разному, и описанный выше путь цикла всегда казался самым грязным. ES6 Object.setPrototypeOf() позволяет делегировать объект переопределения свойства объекту "свойства по умолчанию", в значительной степени выполняя то, что вы пытаетесь сделать, но использование Object.setPrototypeOf() имеет некоторые серьезные последствия, такие как отключение оптимизации компилятора браузера для весь script.

Кроме того, как в решении цикла, так и в решении Object.setPrototypeOf() вы остаетесь с ситуацией, когда объект "переопределить свойство" может мутировать объект "свойства по умолчанию":

defaultObj = {
    a: [1, 2]
}
...
overrideObj = {
    b: 3
}
Object.setPrototypeOf(overrideObj, defaultObj);
console.log(overrideObj); // {a: [1, 2], b: 3}
// Great!
...
overrideObj.a.push(4);
console.log(defaultObj); // {a: [1, 2, 4]}
// Uh-oh.

Вы можете подумать, что это не проблема, но позвольте сказать, что вы используете этот объект в качестве конфигурации для сторонней библиотеки. Теперь вы передаете свой объект по умолчанию и все ссылки на него в стороннюю библиотеку.

Лучшим решением может быть использование JSON.stringify и JSON.parse для копирования и объединения объектов. Здесь Gist с примером: https://gist.github.com/spikesagal/6f7822466887f19b9c65

НТН

Ответ 3

Не то, чтобы я знал, нет. Кроме того, вы захотите написать свой метод слияния следующим образом:

function mergeInto(o1, o2) {
  if (o1 == null || o2 == null)
    return o1;

  for (var key in o2)
    if (o2.hasOwnProperty(key))
      o1[key] = o2[key];

  return o1;
}

Ответ 4

Вы можете сделать следующее, используя собственный JS 1.7, без необходимости создания фреймворка. Пример fiddle (пример предназначен только для простых объектов - не сложных вложенных объектов)

var obj1 = {a: "a", b: "b"};
var obj2 = {c: "c", d: "d"};

// The magic: ugly but works perfectly
var value = (JSON.stringify(obj1).concat(JSON.stringify(obj2))).replace("}{", ",");

document.getElementById("lbl1").setAttribute("value", value);

// back to object
var obj3 = JSON.parse(value);
document.getElementById("lbl2").setAttribute("value", obj3.a + " " + obj3.b + " " + obj3.c + " " + obj3.d);

Ответ 5

Используя ES6 (ES2015), вы можете использовать метод Object.assign:

var x = {a:1, b:2};
var y = {c:3, d:4};
var z = Object.assign({},x,y);

Используя ES7 (ES2016, Chrome 60+ или Babel), вы можете использовать Оператор распространения объектов:

var x = {a:1, b:2};
var y = {c:3, d:4}; 
var z = {...x, ...y};

Ответ 6

В ECMA- Script нет собственных путей, используйте:

function merge(o1,o2) {
 if (typeof(o1)!=='object') o1={};
 if (typeof(o2)!=='object') o2={};
 for (var k in o2) {
 if (o1[k]!==undefined)
  alert ('Collision Error'); // TODO
 else
   o1[k]=o2[k];
 }
 return o1;
}

Ответ 7

Вот функция, которую вы можете использовать для решения своей дилеммы.

код:

  var a = {'a':'1', 'b':'2'};
   var b = {'c':'3', 'd':'4'};

   function appendObj(a,b) {
         var aZ = 'abcdefghijklmnopqrstuvwxyz'.split('');

         bKeys = Object.keys(b);

         for (var i = 0; i < bKeys.length; i++) {
                 a[bKeys[i]] = b[bKeys[i]];
         }
         return a;
   }
   var newObj = appendObj(a,b);

console.log(newObj)

Надеюсь, это поможет.

Примечание Я ввел это через свой телефон, поэтому прошу прощения, если есть семантические ошибки или опечатки.

Все самое лучшее,

Matt

Ответ 8

Ниже я включил функцию глубокого слияния, которую я написал. Это не приведет к глубокому объединению массивов, а только к объектам. Он примет два объекта и вернет третий, новый объект.

var merge = function(o1, o2) {
    var o_new = {};
    for(p in o1) {
        if(o1[p]) {
            if(typeof o1[p] == 'object' && !(o1[p] instanceof Array) && o2.hasOwnProperty(p)) {
                o_new[p] = merge(o1[p], o2[p]);
            }
            else {
                o_new[p] = o1[p];
            }
        }
    }
    for(p in o2) {
        if(typeof o2[p] == 'object' && !(o2[p] instanceof Array) && o1.hasOwnProperty(p)) {
            o_new[p] = merge(o1[p], o2[p]);
        }
        else {
            o_new[p] = o2[p];
        }
    }
    return o_new;
}