Как динамически объединить свойства двух объектов JavaScript? - PullRequest
2173 голосов
/ 05 октября 2008

Мне нужно иметь возможность объединять два (очень простых) объекта JavaScript во время выполнения. Например, я хотел бы:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

obj1.merge(obj2);

//obj1 now has three properties: food, car, and animal

Кто-нибудь имеет сценарий для этого или знает встроенный способ сделать это? Мне не нужна рекурсия, и мне не нужно объединять функции, только методы для плоских объектов.

Ответы [ 60 ]

1 голос
/ 08 февраля 2012

В YUI Y.merge должны выполнить работу:

Y.merge(obj1, obj2, obj3....) 
1 голос
/ 14 октября 2015

Вы можете объединить объекты, следуя моему методу

var obj1 = { food: 'pizza', car: 'ford' };
var obj2 = { animal: 'dog' };

var result = mergeObjects([obj1, obj2]);

console.log(result);
document.write("result: " + JSON.stringify(result, 0, 3) + "
"); function mergeObjects (objectArray) { if (objectArray.length) { var b = "", i = -1; while (objectArray [++ i]) { var str = JSON.stringify (objectArray [i]); b + = str.slice (1, str.length - 1); if (objectArray [i + 1]) b + = ","; } return JSON.parse ("{" + b + "}"); } вернуть {}; }
1 голос
/ 17 января 2019

let obj1 = {a:1, b:2};
let obj2 = {c:3, d:4};
let merged = {...obj1, ...obj2};
console.log(merged);
1 голос
/ 13 марта 2009

Правильная реализация в Прототип должна выглядеть так:

var obj1 = {food: 'pizza', car: 'ford'}
var obj2 = {animal: 'dog'}

obj1 = Object.extend(obj1, obj2);
0 голосов
/ 01 октября 2012

Это объединяет obj в значение по умолчанию def. obj имеет приоритет для всего, что существует в обоих, поскольку obj копируется в def. Обратите внимание, что это рекурсивно.

function mergeObjs(def, obj) {
    if (typeof obj == 'undefined') {
        return def;
    } else if (typeof def == 'undefined') {
        return obj;
    }
    for (var i in obj) {
        if (obj[i] != null && obj[i].constructor == Object) {
            def[i] = mergeObjs(def[i], obj[i]);
        } else {
            def[i] = obj[i];
        }
    }
    return def;
}

a = {x : {y : [123]}}
b = {x : {z : 123}}
console.log(mergeObjs(a, b));
// {x: {y : [123], z : 123}}
0 голосов
/ 12 июня 2017

использование object.assign

Object.prototype.assign = Object.assign && function () {
    var a = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        a[_i] = arguments[_i];
    }
    var src = a.slice(1);
    var target = a[0];
    for (var o in src) {
        if (src.hasOwnProperty(o)) {
            var keys = Object.keys(src[o]);
            var _src = src[o];
            for (var k in keys) {
                if (keys.hasOwnProperty(k)) {
                    var _key = keys[k];
                    target[_key] = _src[_key];
                }
            }
        }
    }
    return target;
};
0 голосов
/ 05 мая 2017
<code><pre>
/**
This script can merge two multi dimensional associative array/objects in javascript by comparing given object with its reference and 
will remove additional given keys, adding missed parameteres and also validating values without overhead. Also it will return the default values if no input presented with re-usable reference!
Tested on IE8 and greater.
**/
var module = (function(){
    //To make our reference variable onchangable, have to put it into a function which is fster and more efficient than "JSON.parse(JSON.stringify(VARIABLE))"
    var _defs = function(){
            return {
                   //string, number and boolean are actually regex based validation keys on input values.
                a: ["string", 'Defaul value for "a"'],
                b: ["number", 300],
                c: ["boolean", true],
                d: {
                  da: ["boolean", true],
                  db: ["string", 'Defaul value for "db"'],
                  dc: {
                    dca: ["number", 200],
                    dcb: ["string", 'Default value for "dcb"'],
                    dcc: ["number", 500],
                    dcd: ["boolean", true]
                  },
                  dce: ["string", 'Default value for "dce"'],
                },
                e: ["number", 200],
                f: ["boolean", 0],
                g: ["", 'This is an internal extra parameter']
            }
        }

        var _validation = {
                number: function (defaultValue, userValue) {
                  if(/^[0-9]+$/.test(userValue)) //Only numbers allowed
                    return userValue;
                  else return defaultValue;
                },
                string: function (defaultValue, userValue) {
                  if(/^[a-zA-Z\s]*$/.test(userValue)) //Only A to Z case insentitive with space aloowed.
                    return userValue;
                  else return defaultValue;
                },
                boolean: function (defaultValue, userValue) {
                  if(typeof userValue === 'boolean') //True or False or 0 ,1
                    return userValue;
                  else return defaultValue;
                }
        }

        var _uniqueMerge = function(opts, _ref){
                for(var key in _ref)
                    if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object)
                      _ref[key] = _uniqueMerge((opts ? opts[key] : null ), _ref[key] );
                    else if(opts && opts.hasOwnProperty(key))
                      _ref[key] = _validation[_ref[key][0]](_ref[key][1], opts[key]); //or without validation on user enties => ref[key] = obj[key]
                    else _ref[key] = _ref[key][1];
                return _ref;
        }
        var _get = function(inputs){
            return _uniqueMerge(inputs, _defs());
        }
        return {
            options: function(){
            return _get(arguments[0] || null); // for more safety and control on number of input variables! used --> ( arguments[0] || null )
            }
        }
})();


//How to use it:    

input_one = { 
    a : "Hello World", 
  //b : ["number", 400], //User missed this parameter
    c: "Hi",
    d : {
        da : false,
        db : "Hellow! World", // ! is not allowed
        dc : {
            dca : 10,
            dcb : "My String",
            dcc: "3thString",
            dcd : false
      },
      dce: "ANOTHER STRING",
    },
    e: 40,
    f: true,
    z: 'x'
};
console.log( JSON.stringify( module.options(input_one), null ,2 ) );
//Output:
/*
{
  "a": "Hello World",
  "b": 300,
  "c": true,
  "d": {
    "da": false,
    "db": "Defaul value for \"db\"",
    "dc": {
      "dca": 10,
      "dcb": "My String",
      "dcc": 500,
      "dcd": false
    },
    "dce": "ANOTHER STRING"
  },
  "e": 40,
  "f": true,
  "g": "This is an internal extra parameter"
}
*/
input_two = { 
    a : 32,
  //b : ["number", 400], //User missed this parameter
    c: "Hi",
    d : {
        da : false,
        db : "HelloWorld",
        dc : {
            dca : 10,
            dcb : "My String",
            dcd : false
      },
      dce: 73,
    }
};
console.log( JSON.stringify( module.options(input_two), null ,2 ) );
//output
/*
{
  "a": "Defaul value for \"a\"",
  "b": 300,
  "c": true,
  "d": {
    "da": false,
    "db": "HelloWorld",
    "dc": {
      "dca": 10,
      "dcb": "My String",
      "dcc": 500,
      "dcd": false
    },
    "dce": "Default value for \"dce\""
  },
  "e": 200,
  "f": 0,
  "g": "This is an internal extra parameter"
}
*/
//Empty input will return the default values!
console.log( JSON.stringify( module.options(), null ,2 ) );     
//Output
/*  
{
  "a": "Defaul value for \"a\"",
  "b": 300,
  "c": true,
  "d": {
    "da": true,
    "db": "Defaul value for \"db\"",
    "dc": {
      "dca": 200,
      "dcb": "Default value for \"dcb\"",
      "dcc": 500,
      "dcd": true
    },
    "dce": "Default value for \"dce\""
  },
  "e": 200,
  "f": 0,
  "g": "This is an internal extra parameter"
}
*/
0 голосов
/ 20 апреля 2017

Объединение JSON-совместимых объектов JavaScript

Я поощряю использование и использование неразрушающих методов, которые не изменяют исходный источник, 'Object.assign' является разрушительным методом , и он также оказывается не таким дружественным для производства , потому что он перестает работать в более ранних браузерах, и у вас нет возможности исправить его с помощью альтернативы.

Объединение объектов JS всегда будет вне досягаемости или неполным, независимо от решения. Но объединение совместимых с JSON совместимых объектов находится всего в одном шаге от возможности написания простого и переносимого фрагмента кода неразрушающего метода объединения серии объектов JS в возвращаемый мастер, содержащий все уникальные имена свойств и их соответствующие значения, синтезированные в один главный объект по назначению.

Имея в виду, что MSIE8 является первым браузером, добавившим встроенную поддержку объекта JSON, это большое облегчение, и повторное использование уже существующей технологии всегда приветствуется.

Ограничение вашего кода стандартными объектами компиляции JSON является скорее преимуществом, чем ограничением, поскольку эти объекты также могут передаваться через Интернет. И, конечно же, для тех, кому нужна более глубокая обратная совместимость, всегда есть плагин json, методы которого можно легко назначить переменной JSON во внешнем коде без необходимости изменять или переписывать используемый метод.

function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }

(Конечно, всегда можно дать ему более осмысленное имя, которое я еще не решил; вероятно, следует назвать его JSONmerge)

Вариант использования:

var master = Merge( obj1, obj2, obj3, ...objn );

Теперь, в отличие от Object.assign, это оставляет все объекты нетронутыми и в их исходном состоянии (в случае, если вы сделали что-то не так и вам нужно изменить порядок объектов объединения или иметь возможность использовать их отдельно для какой-либо другой операции перед объединением их снова).

Количество аргументов слияния также ограничено только пределом длины аргументов [который огромен]. Собственно поддерживаемый синтаксический анализ / stringify JSON уже оптимизирован для машины, что означает: он должен быть быстрее любой скриптовой формы цикла JS. Итерация по заданным аргументам выполняется с использованием while - проверенного самого быстрого цикла в JS.

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

;
var obj1 = {a:1}, obj2 = {b:2}, obj3 = {c:3}
;
function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }
;
var master = Merge( obj1, obj2, obj3 )
;
console.log( JSON.stringify( master ) )
;
0 голосов
/ 29 июля 2013

Вы можете назначить каждому объекту метод слияния по умолчанию (возможно, «наследовать» более подходящее имя):

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

Приведенный ниже код обрабатывает замену объединенных значений, если это необходимо:

Object.prototype.merge = function(obj, override) {
// Don't override by default

    for (var key in obj) {
        var n = obj[key];
        var t = this[key];
        this[key] = (override && t) ? n : t;
    };

};

Данные испытаний приведены ниже:

var Mammal = function () {
    this.eyes = 2;
    this.thinking_brain = false;
    this.say = function () {
    console.log('screaming like a mammal')};
}

var Human = function () {
    this.thinking_brain = true;
    this.say = function() {console.log('shouting like a human')};
}

john = new Human();

// Extend mammal, but do not override from mammal
john.merge(new Mammal());
john.say();

// Extend mammal and override from mammal
john.merge(new Mammal(), true);
john.say();
0 голосов
/ 30 декабря 2015

Возможный способ добиться этого - следующий.

if (!Object.prototype.merge){
    Object.prototype.merge = function(obj){
        var self = this;
        Object.keys(obj).forEach(function(key){
            self[key] = obj[key]
        });
    }
};

Я не знаю, лучше ли это, чем другие ответы. В этом методе вы добавляете прототип merge function к Objects. Таким образом, вы можете позвонить obj1.merge(obj2);

Примечание: вы должны проверить свой аргумент, чтобы увидеть, является ли он объектом, и «бросить» правильный Error. Если нет, Object.keys выдаст сообщение об ошибке

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...