Как динамически объединить свойства двух объектов JavaScript?

Для Symfony3.4 (4) я использовал EntityManagerInterface для обновления пользователя и Security , чтобы получить пользователя, выполнив следующие коды:

app / config / services.yml

AppBundle\Service\ActivityListener:
    tags:
        - { name: 'kernel.event_listener', event: 'kernel.controller', method: onCoreController }

Сервис / ActivityListener.php

<?php
namespace AppBundle\Service;

use AppBundle\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\Security\Core\Security;

class ActivityListener
{
    private $em;
    private $security;

  public function __construct(EntityManagerInterface $em, Security $security)
  {
    $this->em = $em;
    $this->security = $security;
  }

  public function onCoreController(FilterControllerEvent $event)
  {
    // Check that the current request is a "MASTER_REQUEST"
    // Ignore any sub-request
    if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
        return;
    }

    // Check token authentication availability
    if ($this->security->getToken()) {
        $user = $this->security->getToken()->getUser();

        if ( ($user instanceof User) && !($user->isActiveNow()) ) {
            $user->setLastActivityAt(new \DateTime());
            $this->em->flush($user);
        }
    }
  }
}
2255
задан 4 revs, 4 users 64% 7 September 2017 в 16:32
поделиться

10 ответов

Стандартный метод 2018 года ECMAScript

Вы использовали бы , объект распространился :

let merged = {...obj1, ...obj2};

/** There's no limit to the number of objects you can merge.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = {...obj1, ...obj2, ...obj3};

Вот также документация MDN для этого синтаксиса, и если Вы будете использовать столпотворение то - Вам будет нужно этот плагин для него для работы.

2015 ECMAScript (ES6) Стандартный метод

/* For the case in question, you would do: */
Object.assign(obj1, obj2);

/** There's no limit to the number of objects you can merge.
 *  All objects get merged into the first object. 
 *  Only the object in the first argument is mutated and returned.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = Object.assign({}, obj1, obj2, obj3, etc);

(см. Ссылка JavaScript MDN )

<час>

Метод для ES5 и Ранее

for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }

Примечание, что это просто добавит все атрибуты obj2 к obj1, который не мог бы быть тем, что Вы хотите, если Вы все еще хотите использовать неизмененный obj1.

при использовании платформы, которая гадит на всем протяжении прототипов затем, необходимо стать более необычными с проверками как hasOwnProperty, но тот код будет работать на 99% случаев.

функция В качестве примера:

/**
 * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
 * @param obj1
 * @param obj2
 * @returns obj3 a new object based on obj1 and obj2
 */
function merge_options(obj1,obj2){
    var obj3 = {};
    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
    return obj3;
}
2587
ответ дан 14 revs, 11 users 37% 8 September 2017 в 02:32
поделиться

Прототип имеет это:

Object.extend = function(destination,source) {
    for (var property in source)
        destination[property] = source[property];
    return destination;
}

obj1.extend(obj2) сделает то, что Вы хотите.

13
ответ дан 2 revs, 2 users 80% 8 September 2017 в 02:32
поделиться
  • 1
    gdb-6.3 doesn' t работают с emacs' режим s gdb. Я установил gdb-7.5 использование Вашего метода, и это работает теперь:) – RockU 5 October 2012 в 14:15

jQuery также имеет утилиту для этого: http://api.jquery.com/jQuery.extend/ .

Взятый из документации jQuery:

// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options  = { validate: true, name: "bar" };
jQuery.extend(settings, options);

// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }

вышеупомянутый код видоизменится существующий объект названный settings .

<час>

, Если Вы хотите создать новый объект , не изменяя ни один аргумент, используйте это:

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);

// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.
1174
ответ дан 7 revs, 7 users 37% 8 September 2017 в 02:32
поделиться

Данные решения должны быть изменены для проверки source.hasOwnProperty(property) в эти for..in циклы прежде, чем присвоиться - иначе, Вы заканчиваете тем, что копировали свойства целой опытной цепочки, которая редко желаема...

41
ответ дан Christoph 8 September 2017 в 02:32
поделиться

Я погуглил, чтобы код объединил свойства объектов и закончился здесь. Однако с тех пор не было никакого кода для рекурсивного слияния, которое я записал этому сам. (Возможно, jQuery расширяется, рекурсивный BTW?) Во всяком случае надо надеяться, кто-то еще найдет это полезным также.

(Теперь код не использует Object.prototype :)

Код

/*
* Recursively merge properties of two objects 
*/
function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      } else {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

, пример

o1 = {  a : 1,
        b : 2,
        c : {
          ca : 1,
          cb : 2,
          cc : {
            cca : 100,
            ccb : 200 } } };

o2 = {  a : 10,
        c : {
          ca : 10,
          cb : 20, 
          cc : {
            cca : 101,
            ccb : 202 } } };

o3 = MergeRecursive(o1, o2);

Производит объект o3 как

o3 = {  a : 10,
        b : 2,
        c : {
          ca : 10,
          cb : 20,
          cc : { 
            cca : 101,
            ccb : 202 } } };
256
ответ дан Markus 8 September 2017 в 02:32
поделиться

Корректная реализация в Прототип должна быть похожей на это:

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

obj1 = Object.extend(obj1, obj2);
1
ответ дан 2 revs, 2 users 56%Tobi 8 September 2017 в 02:32
поделиться

В MooTools есть Object.merge () :

Object.merge(obj1, obj2);
10
ответ дан 22 November 2019 в 19:55
поделиться

Для не слишком сложных объектов можно использовать JSON:

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

objMerge = JSON.stringify(obj1) + JSON.stringify(obj2);

// {"food": "pizza","car":"ford"}{"animal":"dog","car":"chevy"}

objMerge = objMerge.replace(/\}\{/, ","); //  \_ replace with comma for valid JSON

objMerge = JSON.parse(objMerge); // { food: 'pizza', animal: 'dog', car: 'chevy'}
// Of same keys in both objects, the last object's value is retained_/

Учтите, что в этом примере "}{" не должно встречаться внутри строки!

19
ответ дан 22 November 2019 в 19:55
поделиться

слияние два объекта с помощью [1 113] Object.assign и оператор распространения.

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

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };
var merge = Object.assign(o1, o2, o3);
console.log(merge)  // {X:10, Y:20, Z:30}
console.log(o1)     // {X:10, Y:20, Z:30}

Правильные пути

  • Object.assign ({}, o1, o2, o3) ==> предназначающийся новый объект

  • {... o1... o2... o3} ==> распространяющиеся объекты

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };

console.log('Does not modify original objects because target {}');
var merge = Object.assign({}, o1, o2, o3);
console.log(merge); // { X: 10, Y: 20, Z: 30 }
console.log(o1)

console.log('Does not modify original objects')
var spreadMerge = {...o1, ...o2, ...o3};
console.log(spreadMerge);
console.log(o1);
1
ответ дан 22 November 2019 в 19:55
поделиться

Кажется, что это должно быть всем, в чем Вы нуждаетесь:

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

var obj1 = { ...obj1, ...obj2 }

После этого obj1 должен теперь иметь следующее значение:

{food: "pizza", car: "ford", animal: "dog"}
0
ответ дан 22 November 2019 в 19:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: