jquery 扩展与角度扩展

Posted

技术标签:

【中文标题】jquery 扩展与角度扩展【英文标题】:jquery extend vs angular extend 【发布时间】:2013-05-23 18:07:49 【问题描述】:

这两个扩展函数有什么区别?

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

虽然 jquery.extend 有据可查,但 angular.extend 缺少详细信息,并且那里的 cmets 没有提供任何答案。 (https://docs.angularjs.org/api/ng/function/angular.extend)。

angular.extend 也提供深拷贝吗?

【问题讨论】:

上面写着by copying all of the properties ,我假设all这个词的意思是everything,在JS世界里是deep copy的同义词。 @Ohgodwhy:我非常怀疑这是一个 deep 副本。如果一个属性(比如,p)引用了一个对象,我会和你打赌,在调用之后,src.pdst.p 都引用了 same 对象。 误导性的角度文档是。 【参考方案1】:

angular.extendjQuery.extend 非常相似。它们都从一个或多个源对象到目标对象执行 shallow 属性复制。比如:

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:我只看到一个显着的区别,那就是jQuery 的extend 允许您只指定一个对象,在这种情况下jQuery 本身就是目标。

共同点:

这是一个浅拷贝。因此,如果 src 有一个属性 p 引用一个对象,dst 将获得一个属性 p 引用 same 对象(不是对象的副本)。

它们都返回目标对象。

它们都支持多个源对象。

它们都按顺序执行多个源对象,因此如果多个源对象具有相同的属性名称,则最后一个源对象将“获胜”。

测试页面:Live Copy | Live Source

<!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>

【讨论】:

另外值得一提的是,jQuery 允许您将布尔值 true 指定为第一个参数,以便进行深层复制。见这里:api.jquery.com/jQuery.extend/… 一个主要区别:extend 仅在存在同名属性时复制值,copy 是复制整个对象,因此如果在 $scope 变量上使用它,则会丢失数据绑定!就像 asafge 的回答所说的那样。 angular.extend() 不会为您复制 getter 和 setter。见github.com/angular/angular.js/issues/8573 @demisx:jQuery 也没有。他们都复制了属性的 value,我可能认为这是正确的行为。【参考方案2】:

两者之间有一个细微的区别,之前的答案中没有提到。

jQuery 的 .extend() 允许您有条件地添加键、值对,前提是值已定义。所以在 jQuery 中,如果 x 未定义,$.extend(, 'a': x ? x : undefined); 将返回

然而,在 Angular 的 .extend() 中,angular.extend(, 'a': x ? x : undefined); 将返回 'a': undefined,即使 x 未定义。所以无论如何,钥匙都会在那里。

这可能是好事也可能是坏事,这取决于您的需要。无论如何,这是两个库之间行为的差异。

【讨论】:

我也遇到了同样的问题。相关示例:plnkr.co/edit/2ca7AfIhgolmwaNaYvY4?p=preview 如果您希望两个函数的行为相同,这绝对是一件坏事。 2014 年甚至有一个拉取请求来解决这个问题,但没有实现:github.com/angular/angular.js/pull/8387【参考方案3】:

1.0.7 angularjs 版本声明扩展和复制方法不再复制 angularjs 内部 $$hashKey 值。

查看发行说明@https://github.com/angular/angular.js/blob/master/CHANGELOG.md

angular.copy/angular.extend:不要在复制/扩展函数中复制 $$hashKey。 (6d0b325f, #1875)

在 Chomre 开发工具方法中对 angular.copy 的快速测试表明它确实进行了深度复制。

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 另一方面做一个浅拷贝。

【讨论】:

“在 Chomre 开发工具方法中对 angular.copy 的快速测试表明它确实进行了深层复制。” 不,它没有。 extend没有,反正我没看copy 啊,copy 有,extend 没有:jsbin.com/eketan/2 但问题是关于extend,而不是copy 是的 - 当我发帖时,您已经非常彻底地回答了扩展问题。我想确保复制方法也得到评估,因为它可以为他们试图完成的事情提供解决方案。 感谢你们两位如此彻底地澄清这件事:)【参考方案4】: AngularJS 中的

.extend() 的工作方式类似于 jQuery 的 .extend()

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);

【讨论】:

以上是关于jquery 扩展与角度扩展的主要内容,如果未能解决你的问题,请参考以下文章

jQuery插件扩展与多库共存

jQuery的扩展与noConflict

jQuery扩展与插件--附源码分析

如何扩展默认角度原理图“ng生成组件”

jquery插件与扩展一

jQuery效果与扩展:左右滑动