Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是Javascript库中mixin()和extend()之间的区别_Javascript_Design Patterns_Extend_Mixins - Fatal编程技术网

什么';这是Javascript库中mixin()和extend()之间的区别

什么';这是Javascript库中mixin()和extend()之间的区别,javascript,design-patterns,extend,mixins,Javascript,Design Patterns,Extend,Mixins,我浏览了各种库,看到extend()经常弹出,但我也看到mixin()出现。YUI既有mixin,也有扩展 这两个概念有什么区别?我什么时候才能决定是混合还是扩展对象 谢谢, 马特为清晰起见进行编辑:它们有时是相同的,有时不是;mixin是用于在多个对象之间重用函数的模式的名称,而extend更像是用于这样做的算法/方法。有些情况下它们是相同的(例如下划线u.extend),有些情况下它们是不同的(backbone.js的extend) 在它们不同的情况下,extend通常会将原型链接到被扩展的

我浏览了各种库,看到extend()经常弹出,但我也看到mixin()出现。YUI既有mixin,也有扩展

这两个概念有什么区别?我什么时候才能决定是混合还是扩展对象

谢谢, 马特

为清晰起见进行编辑:它们有时是相同的,有时不是;mixin是用于在多个对象之间重用函数的模式的名称,而extend更像是用于这样做的算法/方法。有些情况下它们是相同的(例如下划线u.extend),有些情况下它们是不同的(backbone.js的extend)


在它们不同的情况下,extend通常会将原型链接到被扩展的对象,而mixin会将方法列表复制到目标上。

mixin不使用instanceof,但extends可以。mixin允许多重继承,但是通过伪造它,而不是通过正确链接原型

我将展示一个ExtJS示例,但是这个概念适用于任何提供mixin的类库,它们都只是将属性复制到对象,而不是链接原型

Ext.define('Ext.Window', {
    extend: 'Ext.Panel',
    requires: 'Ext.Tool',
    mixins: {
        draggable: 'Ext.util.Draggable'
    }
});

Ext.Window instanceof Ext.Panel //true
Ext.Window instanceof Ext.util.Draggable // false
mixin是向对象添加一些功能而不依赖继承的好方法。如果必须继承某些内容才能获得某些功能,则不能使用来自两个类的功能


Ext JS在想将
Labelable
功能添加到
FieldSet
和其他非输入字段时遇到了这个问题。它无法从
字段中的
可标记的
行为中获益,因为它们无法扩展
字段
,因为它也包含所有的输入行为。

您完全可以使用extends创建mixin

mixin提供了多重继承的所有好处,没有层次结构(JavaScript中的原型继承)。它们都允许您在多个对象上重用一个接口(或一组函数)。使用mixin,您不会遇到父子关系中可能遇到的“钻石问题”

当一个对象从两个对象继承相同的函数(甚至函数名)时,就会出现菱形问题。为什么?如果这两个对象中的一个修改了函数,添加了功能(即在Java中称为“super”),JavaScript就不知道如何解释/组合这两个方法了。混血是避免这种继承权的一种方式。它们定义了可以粘贴到任何地方的功能。mixin通常也不包含自己的数据

例如,我可以用jQuery中的
$.extend()
编写一个mixin。
var newmixin=$。extend({},mixin1,mixin2)
将组合两个接口,并将它们展平(覆盖名称冲突)

这里有三件事需要考虑:

  • 两个接口的组合是否具有“层次结构”即。 父/子关系。在JavaScript中,这意味着原型继承
  • 这些函数是复制的还是引用的?如果原始方法更改,继承的方法也会更改吗
  • 当两个同名的方法组合在一起时会发生什么?如何处理这些冲突

  • extend方法在JavaScript库中非常常见,通常是一种允许使用代码的用户将一个或多个对象的所有“自有”属性和方法添加到目标对象上的方法。代码通常非常简单:迭代第一个参数之外的每个参数的所有键,并将存储在那里的值复制到第一个参数

    “Mixin”指的是一种设计模式,在这种模式中,您使用一个对象作为特定属性集和方法的容器,您希望在系统中的多个对象之间共享这些属性和方法。例如,您可能有可以应用于应用程序中所有UI组件的宽度和高度getter和setter,因此在JavaScript的情况下,您可以创建一个可以用“new”实例化的函数,或者创建一个保存这些方法的对象文本。然后可以使用“extend”类型函数将这些方法复制到系统中任意数量的对象上

    下划线有一个mixin方法,它本质上只是一个扩展,其中所有传入对象的方法都添加到基本下划线对象中以用于链接。jQuery使用其扩展方法jQuery.fn做了类似的事情

    就我个人而言,我喜欢保持extend as is,即“将所有内容从这些对象复制到这个对象”类型的行为,同时使用一个单独的mixin方法,该方法只接受一个源对象,然后将所有进一步的参数作为要复制的属性和方法的名称(如果只传入目标和源,而没有进一步的参数,那么它的行为就像单个源扩展)

    e、 g


    除非你想要两个类提供的行为。除非你进入多重继承,否则不能使用继承,因为多重继承有它自己的问题。我不确定这两者之间有什么关系,因为extend和mixin与继承没有直接关系,等等,它们只是一种模仿这种行为的方法。我只是解释一下这个案例在这里,它们没有相同的行为。啊,我明白你的意思。我猜有些库使用extend链接原型,这只能做一次,其中mixin会倾向于一对一地复制它。当然,不是所有库都这样做,所以这是一个重要的区别。这个答案非常具体,不是吗o Ext.js,不适用于许多其他JavaScript库(jQuery和下划线只是两个示例)。@natlee75我的回答是,mixin不使用原型链,并且它失败了
    instanceof
    测试,Ext-js是它们的一个实现(它们让你以不同的方式检查某个东西是否是mixin).据我所知,jquery或下划线不通过设置它们来实现混合
    function mixin(target, source) {
        function copyProperty(key) {
            target[key] = source[key];
        }
    
        if (arguments.length > 2) {
            // If there are arguments beyond target and source then treat them as
            // keys of the specific properties/methods that should be copied over.
            Array.prototype.slice.call(arguments, 2).forEach(copyProperty);
        } else {
            // Otherwise copy all properties/methods from the source to the target.
            Object.keys(source).forEach(copyProperty);
        }
    }