2013-04-12 56 views
2

我伸出骨干的观点一样:骨干观的继承共享属性

var baseView = Backbone.View.extend({ 
    fruits : [], 
    listFruits : function() { 
     console.log(this.fruits); 
    } 
}); 

var firstView = baseView.extend({ 
    initialize : function() { 
     this.fruits.push("apple"); 
    } 
}); 

var secondView = baseView.extend({ 
    initialize : function() { 
     this.fruits.push("pear"); 
    } 
}); 


var firstViewInstance = new firstView(); // ["apple", "pear"] 
var secondViewInstance = new secondView(); // ["apple", "pear"] 

firstViewInstance.listFruits(); 
secondViewInstance.listFruits(); 

在我看来,firstViewInstancesecondViewInstance应该是完全独立的,但它们有明显的关联。我怎样才能实现两个独立的视图对象,都从一个共同的基础继承,但不是共享数据?

编辑: 基于下面的答案我有一个更新的小提琴在http://jsfiddle.net/qZ7SU/似乎解决这个问题。我仍然不完全清楚发生了什么,但我认为明确附加fruits[]this,将其创建为实例变量,而不是将其附加到原型。

+0

你这里的问题是,'[]'是一个数组,因此一个对象,所以是独一无二的原型和所有的意见都维护着一个相同。一个简单的解决方案,但涉及大量的样板将在初始化函数中添加this.fruits = []。另一个可能是重写baseView的构造函数。我会解释那部分是你感兴趣的。我会尝试去想另一个解决方案。 – Loamhoof

回答

4

这是因为对原始fruits -property的引用是被复制到子视图的引用。见underscore.js extend

_.extend = function(obj) { 
    each(slice.call(arguments, 1), function(source) { 
    if (source) { 
     for (var prop in source) { 
     obj[prop] = source[prop]; 
     } 
    } 
    }); 
    return obj; 
}; 

从公共基础继承,但不能共享数据,您需要初始化的初始化函数的非共用性。

var baseView = Backbone.View.extend({ 
    initialize: function() { 
    this._initializeBase(); 
    }, 

    _initializeBase: function() { 
    this.fruits = []; 
    }, 

    listFruits : function() { 
    console.log(this.fruits); 
    } 
}); 

var firstView = baseView.extend({ 
    initialize : function() { 
    this._initializeBase(); 
    this.fruits.push("apple"); 
    } 
}); 

这种方式属性将被添加到对象,当它被初始化和数据不会被共享。

希望这会有所帮助!

+0

谢谢,这清除了一些东西,我已经采取了你所说的,但通过调用原型初始化略有不同,并更新了现在似乎http://jsfiddle.net/uNBSW/10/小提琴做我想做的事。我仍然发现整个Javascript原型继承非常混乱。更喜欢经典的OOP概念! – Mark

+0

Javascript有它的陷阱,但它也提供了一个更灵活的方式来做某些事 – jakee

2

我写了一篇关于这个更详细的blog post但最简单的方法是提供一种确保fruits每个子视图的原型创建一个自定义的构造函数,而不是在所有子视图继承baseView.prototype

var baseView = Backbone.View.extend({ 
    constructor: function() { 
    this.fruits = []; 
    Backbone.View.apply(this, arguments); 
    }, 
    listFruits : function() { 
    console.log(this.fruits); 
    } 
}); 

var firstView = baseView.extend({ 
    initialize : function() { 
     this.fruits.push("apple"); 
    } 
}); 

var secondView = baseView.extend({ 
    initialize : function() { 
     this.fruits.push("pear"); 
    } 
}); 


var firstViewInstance = new firstView(); // ["apple"] 
var secondViewInstance = new secondView(); // ["pear"] 
+0

同意,这应该是明显的答案。从继承的视图调用'initialize'是一种反模式imo。 –