Расширение jquery против углового расширения

В чем разница между этими двумя функциями расширения?

  angular.extend(a,b);
  $.extend(a,b);

В то время как jquery.extend хорошо документирован, в angular.extend отсутствуют подробности, а комментарии не дают ответов. (https://docs.angularjs.org/api/ng/function/angular.extend).

Предоставляет ли angular.extend глубокую копию?


person Renaud    schedule 28.05.2013    source источник
comment
В нем указано by copying all of the properties , и я бы предположил, что использование слова all означает everything, что является синонимом deep copy в мире JS.   -  person Ohgodwhy    schedule 28.05.2013
comment
@Ohgodwhy: я очень сомневаюсь, что это глубокая копия. Если свойство (скажем, p) относится к объекту, ставлю доллары на пончики, что после вызова и src.p, и dst.p относятся к одному и тому же объекту.   -  person T.J. Crowder    schedule 28.05.2013
comment
Вводящая в заблуждение угловая документация.   -  person Ohgodwhy    schedule 28.05.2013


Ответы (4)


angular.extend и jQuery.extend очень похожи. Оба они выполняют поверхностное копирование свойства из одного или нескольких исходных объектов в конечный объект. Так, например:

var src = {foo: "bar", baz: {}};
var dst = {};
whatever.extend(dst, src);
console.log(dst.foo);             // "bar"
console.log(dst.baz === src.baz); // "true", it's a shallow copy, both
                                  // point to same object

angular.copy предоставляет глубокую копию:

var src = {foo: "bar", baz: {}};
var dst = angular.copy(src);
console.log(dst.baz === src.baz); // "false", it's a deep copy, they point
                                  // to different objects.

Возвращаясь к extend: я вижу только одно существенное отличие: extend в jQuery позволяет указать только один объект, и в этом случае целью является сам jQuery.

Общие вещи:

  • Это мелкая копия. Таким образом, если src имеет свойство p, которое ссылается на объект, dst получит свойство p, которое ссылается на тот же объект (а не на копию объекта).

  • Оба они возвращают целевой объект.

  • Оба они поддерживают несколько исходных объектов.

  • Они оба выполняют несколько исходных объектов по порядку, поэтому последний исходный объект будет "выигрывать", если несколько исходных объектов имеют одно и то же имя свойства.

Тестовая страница: Динамическое копирование | Текущий источник

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<meta charset=utf-8 />
<title>Extend!</title>
</head>
<body>
  <script>
    (function() {
      "use strict";
      var src1, src2, dst, rv;

      src1 = {
        a: "I'm a in src1",
        b: {name: "I'm the name property in b"},
        c: "I'm c in src1"
      };
      src2 = {
        c: "I'm c in src2"
      };

      // Shallow copy test
      dst = {};
      angular.extend(dst, src1);
      display("angular shallow copy? " + (dst.b === src1.b));
      dst = {};
      jQuery.extend(dst, src1);
      display("jQuery shallow copy? " + (dst.b === src1.b));
      $("<hr>").appendTo(document.body);

      // Return value test
      dst = {};
      rv = angular.extend(dst, src1);
      display("angular returns dst? " + (rv === dst));
      dst = {};
      rv = jQuery.extend(dst, src1);
      display("jQuery returns dst? " + (rv === dst));
      $("<hr>").appendTo(document.body);

      // Multiple source test
      dst = {};
      rv = angular.extend(dst, src1, src2);
      display("angular does multiple in order? " +
                  (dst.c === src2.c));
      dst = {};
      rv = jQuery.extend(dst, src1, src2);
      display("jQuery does multiple in order? " +
                  (dst.c === src2.c));

      function display(msg) {
        $("<p>").html(String(msg)).appendTo(document.body);
      }
    })();
  </script>
</body>
</html>
person T.J. Crowder    schedule 28.05.2013
comment
Также стоит упомянуть, что jQuery позволяет указать логическое значение true в качестве первого аргумента для создания глубокой копии. См. здесь: api.jquery.com/jQuery. расширить/ - person treeface; 06.11.2013
comment
Одно существенное отличие: расширение копирует только значения, если есть свойство с таким же именем, копия копирует весь объект, поэтому вы теряете привязку данных, если используете ее для переменной $scope! Как говорится в ответе Асафге. - person Sebastian; 11.09.2014
comment
angular.extend() не будет копировать геттеры и сеттеры для вас. См. github.com/angular/angular.js/issues/8573. - person demisx; 30.10.2014
comment
@demisx: jQuery тоже. Оба они копируют value свойства, что, я бы сказал, является правильным поведением. - person T.J. Crowder; 30.10.2014

Между ними есть одно тонкое различие, которое не упоминалось в предыдущих ответах.

.extend() в jQuery позволяет условно добавлять пары ключ-значение, только если значение определено. Итак, в jQuery это: $.extend({}, {'a': x ? x : undefined}); вернет {} в случае, если x не определено.

Однако в .extend() Angular это: angular.extend({}, {'a': x ? x : undefined}); вернет {'a': undefined}, даже если x не определено. Так что ключ будет там, несмотря ни на что.

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

person asafge    schedule 14.03.2014
comment
У меня тоже такая же проблема. связанный пример здесь: plnkr.co/edit/2ca7AfIhgolmwaNaYvY4?p=preview - person gotoweb; 22.01.2015
comment
Это определенно плохо, если вы ожидаете, что обе функции будут вести себя одинаково. В 2014 году даже был запрос на включение, чтобы исправить это, но он не был реализован: github.com /angular/angular.js/pull/8387 - person Waruyama; 10.10.2018

В сборке angularjs версии 1.0.7 указано, что методы расширения и копирования больше не копируют внутренние значения angularjs $$hashKey.

См. примечания к выпуску @ https://github.com/angular/angular.js/blob/master/CHANGELOG.md

angular.copy/angular.extend: не копируйте $$hashKey в функциях копирования/расширения. (6d0b325f, #1875)

Быстрый тест angular.copy в методе инструментов разработки Chomre показывает, что он делает глубокую копию.

x = {p: 3, y: {x: 5}}
Object {p: 3, y: Object}
x
Object {p: 3, y: Object}
z = angular.copy(x);
Object {p: 3, y: Object}
z
Object {p: 3, y: Object}
x
Object {p: 3, y: Object}
z.y.x = 1000
    1000
x
Object {p: 3, y: Object}
p: 3
y: Object
    x: 5
    __proto__: Object
__proto__: Object
z
Object {p: 3, y: Object}
p: 3
y: Object
   x: 1000
   __proto__: Object
__proto__: Object

angular.extend, с другой стороны, делает поверхностную копию.

person Mike Pugh    schedule 28.05.2013
comment
Быстрая проверка метода angular.copy в инструментах разработки Chomre показывает, что он выполняет глубокое копирование. Нет, это не так. extend во всяком случае, я не смотрел на copy. - person T.J. Crowder; 28.05.2013
comment
Ах, copy да, extend нет: jsbin.com/eketan/2 Но вопрос о extend, а не copy. - person T.J. Crowder; 28.05.2013
comment
Да, вы уже довольно подробно ответили на вопрос о расширении, когда я писал. Я хотел убедиться, что метод копирования также оценивается, поскольку он может обеспечить решение того, что они пытаются выполнить. - person Mike Pugh; 28.05.2013
comment
Спасибо вам обоим за то, что так подробно разъяснили этот вопрос :) - person Renaud; 31.05.2013

.extend() в AngularJS работает аналогично .extend() в jQuery.

http://jsfiddle.net/Troop4Christ/sR3Nj/

var o1 = {
    a: 1,
    b: 2,
    c: {
        d:3,
        e:4
    }
},
    o2 = {
        b: {
            f:{
                g:5
            }
        }
    };


console.log(angular.extend({}, o1, o2));
console.log(o1);
console.log(o2);
person RavenHursT    schedule 08.12.2013