Backbone 中的混合模式 - 它与 Backbone 的扩展实现有何不同?
Mixin pattern in Backbone - how does it differ from Backbone's extend implementation?
最近我一直在阅读 JavaScript 模式和架构。我经常遇到的一个提示是支持组合而不是继承,所以我花了一天时间对此进行了更深入的研究。
了解了组合(更像是混合'n'匹配,即通过工厂)与继承(一种不灵活和模糊的耦合)相比的优势,我想知道如何实际使用这些知识,这导致我去 Mixin pattern.
由于我主要在 Backbone 中进行开发,因此我创建了一个简单的 mixin 以在视图中使用。实际上,我只是将 baseview 的一部分移动到 mixin 中:
之前:
var BaseView = Backbone.View.extend({
getTemplate: function () {
return template;
}
});
var MyView = BaseView.extend({
template: 'dummy',
initialize: function () {
// Do stuff
},
render: function () {
// Do render stuff
}
});
之后:
var myMixin = {
getTemplate: function () {
return template;
}
};
var MyView = Backbone.View.extend({
template: 'dummy'
initialize: function () {
_.extend(this, myMixin)
// Do stuff
},
render: function () {
// Do render stuff
}
});
现在使用 Underscore 的 extend
函数将 getTemplate
方法注入到 MyView
,但这与继承自 BaseView
有何不同,它也使用了一个extend
调用 BaseView.extend
的不同实现方式?这甚至是 Backbone 中的真正继承?
编辑
我相信您在职业生涯中遇到过 "merge" 不是 well-defined 的情况。 "Mixin" 在其他语言和概念中具有精确的含义,但在 Javascript 中,它具有与 "merge" 相同的精确级别和 well-definition,也就是说,不是很多。
您正确地指出,在这两种情况下您都得到了 _.extend
的结果。这是您特定选择 mixin
实现的结果......这是在 initialize
.
中调用 _.extend
mixin
还有其他选择,它们具有更奇特和有用的逻辑来处理合并键中的冲突等。 backbone.cocktail
是我记得的一个。
如果您还没有看过 extend
来自带注释的来源,请执行以下操作。
从注释来源扩展
var extend = function(protoProps, staticProps) {
var parent = 这个;
变量 child;
我们从函数 extend
的签名开始...
The constructor function for the new subclass is either defined by you
(the “constructor” property in your extend definition), or defaulted
by us to simply call the parent constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
换句话说,要么我们已经有了 child 的构造函数,要么我们没有,在这种情况下它会得到 parents.
Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
Set the prototype chain to inherit from parent, without calling
parent‘s constructor function and add the prototype properties.
child.prototype = _.create(parent.prototype, protoProps);
child.prototype.constructor = child;
这是微妙的,但非常重要。请注意,他们可能刚刚完成:child.prototype = parent.prototype
。想想他们为什么不这样做,以及那对你有什么用。
顺便说一句,这两行是整个方法的核心,因为它 1) 给 child 它自己的 parent 原型副本,并给原型 child的构造函数。所以你得到了一个真正独特的原型 child 但从 parent.
扩展而来
Set a convenience property in case the parent’s prototype is needed
later.
child.__super__ = parent.prototype;
return child;
};
下划线扩展呢?
下划线扩展是 merging
的一种方法。它是 Backbone.extend
过程的一部分,但另一部分与实现 inheritance
.
有关
现在 Backbone
的 mixin 库 cocktail
为您提供了比 underscore
更智能的合并处理,因此如果您觉得 [=30],您可能想要寻求更多选择=]太多了。
https://github.com/onsi/cocktail
原始
好吧,我并没有声称要完全实现 diff
之间的 extending
从散列和 mixin
散列,但我确实知道一些事情重要。
首先,extend
需要第二个参数:)
很多人不知道。
var extend = function(protoProps, staticProps) {
有时我看到人们使用 mixin
,因为他们想要不断地改变可以通过 staticProps
实现的目标。
其次,extend
在语义上将扩展关联到 Clazz
... 100 次中有 99 次,您没有看到 extend
的输入被重用。
最近我一直在阅读 JavaScript 模式和架构。我经常遇到的一个提示是支持组合而不是继承,所以我花了一天时间对此进行了更深入的研究。
了解了组合(更像是混合'n'匹配,即通过工厂)与继承(一种不灵活和模糊的耦合)相比的优势,我想知道如何实际使用这些知识,这导致我去 Mixin pattern.
由于我主要在 Backbone 中进行开发,因此我创建了一个简单的 mixin 以在视图中使用。实际上,我只是将 baseview 的一部分移动到 mixin 中:
之前:
var BaseView = Backbone.View.extend({
getTemplate: function () {
return template;
}
});
var MyView = BaseView.extend({
template: 'dummy',
initialize: function () {
// Do stuff
},
render: function () {
// Do render stuff
}
});
之后:
var myMixin = {
getTemplate: function () {
return template;
}
};
var MyView = Backbone.View.extend({
template: 'dummy'
initialize: function () {
_.extend(this, myMixin)
// Do stuff
},
render: function () {
// Do render stuff
}
});
现在使用 Underscore 的 extend
函数将 getTemplate
方法注入到 MyView
,但这与继承自 BaseView
有何不同,它也使用了一个extend
调用 BaseView.extend
的不同实现方式?这甚至是 Backbone 中的真正继承?
编辑
我相信您在职业生涯中遇到过 "merge" 不是 well-defined 的情况。 "Mixin" 在其他语言和概念中具有精确的含义,但在 Javascript 中,它具有与 "merge" 相同的精确级别和 well-definition,也就是说,不是很多。
您正确地指出,在这两种情况下您都得到了 _.extend
的结果。这是您特定选择 mixin
实现的结果......这是在 initialize
.
_.extend
mixin
还有其他选择,它们具有更奇特和有用的逻辑来处理合并键中的冲突等。 backbone.cocktail
是我记得的一个。
如果您还没有看过 extend
来自带注释的来源,请执行以下操作。
从注释来源扩展
var extend = function(protoProps, staticProps) { var parent = 这个; 变量 child;
我们从函数 extend
的签名开始...
The constructor function for the new subclass is either defined by you (the “constructor” property in your extend definition), or defaulted by us to simply call the parent constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
换句话说,要么我们已经有了 child 的构造函数,要么我们没有,在这种情况下它会得到 parents.
Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
Set the prototype chain to inherit from parent, without calling parent‘s constructor function and add the prototype properties.
child.prototype = _.create(parent.prototype, protoProps);
child.prototype.constructor = child;
这是微妙的,但非常重要。请注意,他们可能刚刚完成:child.prototype = parent.prototype
。想想他们为什么不这样做,以及那对你有什么用。
顺便说一句,这两行是整个方法的核心,因为它 1) 给 child 它自己的 parent 原型副本,并给原型 child的构造函数。所以你得到了一个真正独特的原型 child 但从 parent.
扩展而来Set a convenience property in case the parent’s prototype is needed later.
child.__super__ = parent.prototype;
return child;
};
下划线扩展呢?
下划线扩展是 merging
的一种方法。它是 Backbone.extend
过程的一部分,但另一部分与实现 inheritance
.
现在 Backbone
的 mixin 库 cocktail
为您提供了比 underscore
更智能的合并处理,因此如果您觉得 [=30],您可能想要寻求更多选择=]太多了。
https://github.com/onsi/cocktail
原始
好吧,我并没有声称要完全实现 diff
之间的 extending
从散列和 mixin
散列,但我确实知道一些事情重要。
首先,extend
需要第二个参数:)
很多人不知道。
var extend = function(protoProps, staticProps) {
有时我看到人们使用 mixin
,因为他们想要不断地改变可以通过 staticProps
实现的目标。
其次,extend
在语义上将扩展关联到 Clazz
... 100 次中有 99 次,您没有看到 extend
的输入被重用。