Javascript 主干视图扩展奇怪的行为
我最近一直在玩主干视图,在创建自己的视图子类时遇到了一个非常奇怪的行为: 在我看来,在Backbone.View的子类上调用extend()会试图在超类定义中合并对象属性(很抱歉使用了野蛮的措辞)Javascript 主干视图扩展奇怪的行为,javascript,backbone.js,backbone-views,Javascript,Backbone.js,Backbone Views,我最近一直在玩主干视图,在创建自己的视图子类时遇到了一个非常奇怪的行为: 在我看来,在Backbone.View的子类上调用extend()会试图在超类定义中合并对象属性(很抱歉使用了野蛮的措辞) 请考虑以下代码: (function() { var SomeCustomView = Backbone.View.extend({ children : {}, //internal use only _children : {}, counter : 0,
请考虑以下代码:
(function() {
var SomeCustomView = Backbone.View.extend({
children : {},
//internal use only
_children : {},
counter : 0,
initialize : function(options){
},
render : function(){
var t = this;
_.each(this.children, function(child, childId){
if(_.isFunction(child))child=child.call(this);
this._children[childId] = child;
this.counter++;
},t );
return this;
},
});
//register on window object
this.SomeCustomView = SomeCustomView;
}).call(this);
然后创建SomeCustomView的子类:
(function() {
console.error("START STRANGE BUG TEST");
var BetterCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'hi'}
}
});
var instance1 = new BetterCustomView({ id : 'one' });
console.error(" _____________________________ ");
console.error("instance1.counter before render" + instance1.counter);
instance1.render();
console.error("instance1.counter after render" + instance1.counter);
console.error("instance1 _children");
console.error(instance1._children);
console.error("instance1._children.firstChild");
console.error(instance1._children.firstChild);
console.error("instance1._children.secondChild");
console.error(instance1._children.secondChild);
console.error(" _____________________________ ");
var EvenBetterCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'wuazza', foo : 'bar' },
secondChild : { name : 'NotSupposedToBeInUltimate'}
}
});
var instance2 = new EvenBetterCustomView({ id : 'two' });
console.error(" _____________________________ ");
console.error("instance2.counter before render" + instance2.counter);
instance2.render();
console.error("instance2.counter after render" + instance2.counter);
console.error("instance2 _children");
console.error(instance2._children);
console.error("instance2._children.firstChild");
console.error(instance2._children.firstChild);
console.error("instance2._children.secondChild");
console.error(instance2._children.secondChild);
console.error(" _____________________________ ");
var TheUltimateCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'whizzz' }
}
});
var instance3 = new TheUltimateCustomView({ id : 'three' });
console.error(" _____________________________ ");
console.error("instance3.counter before render" + instance3.counter);
instance3.render();
console.error("instance3.counter after render" + instance3.counter);
console.error("instance3 _children");
console.error(instance3._children);
console.error("instance3._children.firstChild");
console.error(instance3._children.firstChild);
console.error("instance3._children.secondChild");
console.error(instance3._children.secondChild);
console.error(" _____________________________ ");
}).call(this);
现在,控制台输出以下内容:
START STRANGE BUG TEST test.html:46
_____________________________ test.html:56
instance1.counter before render0 test.html:58
instance1.counter after render1 test.html:60
instance1 _children test.html:62
Object {firstChild: Object}
test.html:63
instance1._children.firstChild test.html:65
Object {name: "hi"} test.html:66
instance1._children.secondChild test.html:67
undefined test.html:68
_____________________________ test.html:70
_____________________________ test.html:83
instance2.counter before render0 test.html:85
instance2.counter after render2 test.html:87
instance2 _children test.html:89
Object {firstChild: Object, secondChild: Object}
test.html:90
instance2._children.firstChild test.html:92
Object {name: "wuazza", foo: "bar"} test.html:93
instance2._children.secondChild test.html:94
Object {name: "NotSupposedToBeInUltimate"} test.html:95
_____________________________ test.html:97
_____________________________ test.html:110
instance3.counter before render0 test.html:112
instance3.counter after render1 test.html:114
instance3 _children test.html:116
Object {firstChild: Object, secondChild: Object}
test.html:117
instance3._children.firstChild test.html:119
Object {name: "whizzz"} test.html:120
instance3._children.secondChild test.html:121
Object {name: "NotSupposedToBeInUltimate"} test.html:122
_____________________________
请注意,每次在实际测试中,我都会扩展一些CustomView。
注意,在第三个子类UltimateCustomView中,您可以找到在EverbetterCustomView中声明并在render()调用期间放置在_children对象中的“secondChild”
对我来说,至少可以说这是一种非常奇怪的行为
UltimateCustomView并没有更好地扩展声明secondChild的CustomView。此外,我们正在测试_children对象,该对象是在对CustomViewClass的子类实例调用render()时填充的。
它如何在其他子类CustomViewClass中结束
有人能给我解释一下吗?
这是BackBone.View执行其.extend方法的一个错误吗
是我做错了什么吗
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="backbone.js"></script>
<script type="text/javascript">
(function() {
var SomeCustomView = Backbone.View.extend({
children : {},
//internal use only
_children : {},
counter : 0,
initialize : function(options){
},
render : function(){
var t = this;
_.each(this.children, function(child, childId){
if(_.isFunction(child))child=child.call(this);
this._children[childId] = child;
this.counter++;
},t );
return this;
},
});
//register on window object
this.SomeCustomView = SomeCustomView;
}).call(this);
(function() {
console.error("START STRANGE BUG TEST");
var BetterCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'hi'}
}
});
var instance1 = new BetterCustomView({ id : 'one' });
console.error(" _____________________________ ");
console.error("instance1.counter before render" + instance1.counter);
instance1.render();
console.error("instance1.counter after render" + instance1.counter);
console.error("instance1 _children");
console.error(instance1._children);
console.error("instance1._children.firstChild");
console.error(instance1._children.firstChild);
console.error("instance1._children.secondChild");
console.error(instance1._children.secondChild);
console.error(" _____________________________ ");
var EvenBetterCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'wuazza', foo : 'bar' },
secondChild : { name : 'NotSupposedToBeInUltimate'}
}
});
var instance2 = new EvenBetterCustomView({ id : 'two' });
console.error(" _____________________________ ");
console.error("instance2.counter before render" + instance2.counter);
instance2.render();
console.error("instance2.counter after render" + instance2.counter);
console.error("instance2 _children");
console.error(instance2._children);
console.error("instance2._children.firstChild");
console.error(instance2._children.firstChild);
console.error("instance2._children.secondChild");
console.error(instance2._children.secondChild);
console.error(" _____________________________ ");
var TheUltimateCustomView = SomeCustomView.extend({
children : {
firstChild : { name : 'whizzz' }
}
});
var instance3 = new TheUltimateCustomView({ id : 'three' });
console.error(" _____________________________ ");
console.error("instance3.counter before render" + instance3.counter);
instance3.render();
console.error("instance3.counter after render" + instance3.counter);
console.error("instance3 _children");
console.error(instance3._children);
console.error("instance3._children.firstChild");
console.error(instance3._children.firstChild);
console.error("instance3._children.secondChild");
console.error(instance3._children.secondChild);
console.error(" _____________________________ ");
}).call(this);
</script>
</head>
<body>
coucou
</body>
</html>
(功能(){
var SomeCustomView=Backbone.View.extend({
儿童:{},
//仅供内部使用
_儿童:{},
柜台:0,,
初始化:函数(选项){
},
render:function(){
var t=这个;
_.each(this.children,function(child,childId){
如果(u.isFunction(child))child=child.call(this);
这个。_children[childId]=child;
这个.counter++;
},t);
归还这个;
},
});
//窗口对象上的寄存器
this.SomeCustomView=SomeCustomView;
}).打电话(这个);
(功能(){
控制台错误(“启动奇怪的错误测试”);
var BetterCustomView=SomeCustomView.extend({
儿童:{
第一个孩子:{name:'hi'}
}
});
var instance1=new BetterCustomView({id:'one'});
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
console.error(“渲染前的instance1.counter”+instance1.counter);
instance1.render();
console.error(“渲染后的instance1.counter”+instance1.counter);
console.error(“instance1_children”);
控制台错误(实例1.\u子项);
console.error(“instance1._children.firstChild”);
console.error(instance1.\u children.firstChild);
console.error(“instance1.\u children.secondChild”);
console.error(instance1.\u children.secondChild);
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
var EvenBetterCustomView=SomeCustomView.extend({
儿童:{
第一个孩子:{name:'wuazza',foo:'bar'},
第二个子项:{name:'NotAssociatedToBeinUltimate'}
}
});
var instance2=new evenbertercustomview({id:'two'});
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
console.error(“渲染前的instance2.counter”+instance2.counter);
instance2.render();
console.error(“渲染后的instance2.counter”+instance2.counter);
控制台错误(“实例2_子项”);
控制台错误(实例2.\u子项);
console.error(“instance2._children.firstChild”);
console.error(instance2.\u children.firstChild);
console.error(“instance2._children.secondChild”);
console.error(instance2.\u children.secondChild);
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
var TheUltimateCustomView=SomeCustomView.extend({
儿童:{
第一个孩子:{name:'whizzz'}
}
});
var instance3=new TheUltimateCustomView({id:'three'});
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
console.error(“渲染前的instance3.counter”+instance3.counter);
instance3.render();
console.error(“渲染后的instance3.counter”+instance3.counter);
控制台错误(“实例3_子项”);
控制台错误(实例3.\u子项);
console.error(“instance3._children.firstChild”);
console.error(instance3.\u children.firstChild);
console.error(“instance3._children.secondChild”);
console.error(instance3.\u children.secondChild);
控制台错误(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”);
}).打电话(这个);
库库
下面是可以测试此行为的完整html页面:
非常感谢你的帮助 更准确地说,当您这样做时:
(function() {
var SomeCustomView = Backbone.View.extend({
...
//internal use only
_children : {},
...
});
每个实例都有自己的\u子项
字段,但它们都共享相同的初始化值{}
,因此所有扩展SomeCustomView
的视图将共享相同的值,除非将\u子项
更改为另一个值
试着这样做:
(function() {
var SomeCustomView = Backbone.View.extend({
children : {},
//internal use only
_children : null, // or whatever you want
...
render : function(){
this._children = {}; // here your instance will have it's own value
...
},
});
好,但是为什么在渲染之前,每个实例上的计数器值都是0?还有没有其他方法可以定义超类中的_视图,而不必每次在子类中重新定义它?否则,这对我来说似乎非常不合逻辑,因为我希望使用非静态对象“扩展”视图类,即不共享的对象