在骨干视图中,您可以将私有变量和公众放在哪里。
现在我有这样的事情:
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
}
});
我尝试在initialize方法之前添加var myPrivate
,但它引发了错误。只在视图中使用的私有变量在哪里?
答案 0 :(得分:19)
我建议你使用initialize方法作为围绕所有其他方法的闭包。我认为这将使您的行为更符合我们在C ++和Java等经典继承语言中所获得的行为:
myView = Backbone.View.extend({ initialize: function(options){ var myPrivate = "I'm private"; this.myPublic = "I'm public"; this.getPrivate = function () { return myPrivate; }; this.setPrivate = function (value) { if (typeof(value) === 'string') { myPrivate = value; return true; } else { return false; } }; } });
答案 1 :(得分:11)
在一个自我调用的匿名函数中包装它:
(function() {
var myPrivate = 1;
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
myPrivate++;
},
render: function() {
alert(myPrivate);
}
});
})();
编辑:正如下面kaustubh's comment中所指出的,上面的示例创建了一个在实例之间共享的私有变量。您可以创建一种 protected 变量,即可以由View的其他实例读取的实例级变量。为每个实例提供唯一的公共ID,并将实例变量存储在“private static”变量中。然后通过实例id:
访问变量(function() {
var data = [];
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
this.Id = data.length;
data.push({});
data[this.Id].myProtected = "abc";
},
render: function() {
alert(data[this.Id].myProtected)
}
});
})();
或者,您可以在不使用公共ID的情况下执行此操作,但它会变得更复杂:
(function() {
var data = (function () {
var dataValues = [];
return function (instance) {
for (var i = 0; i < dataValues.length; i++) {
if (dataValues[i].instance === instance) {
return dataValues[i].data;
}
}
var dataObject = { instance: instance, data: {} };
dataValues.push(dataObject);
return dataObject.data;
};
})();
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
data(this).myProtected = "abc";
},
render: function() {
alert(data(this).myProtected)
}
});
})();
我正在努力想出一种存储真正私有变量的方法。如果灵感来袭,我会回复。
答案 2 :(得分:1)
而不是直接将对象插入到extend函数中,如何创建一个闭包并从该闭包返回一个对象到extend函数?
var myView = Backbone.View.extend(function () {
var _myPrivateOne = 0;
function _myPrivateStrangeSquareFunction(a) {
return a * a + 1;
}
return {
initialize: function (options) {
_myPrivateOne = options.privateOne;
this.myPublicOne = options.publicOne;
},
setPrivateOne: function (value) {
_myPrivateOne = value;
return _myPrivateOne;
},
getPrivateOne: function () {
return _myPrivateOne;
},
getPrivateOneStrangelySquared: function () {
return _myPrivateStrangeSquareFunction(_myPrivateOne);
}
};
} ());
我没试过这个,因为我现在没有可用的Backbone安装。
答案 3 :(得分:0)
gilly3的解决方案可能是最好的答案,虽然它在技术上不是创建/使用私有变量,因为同一个闭包的其他实例可以访问它(你可能并不关心开发团队的其他成员滥用它特权,但它可能会发生。)
如果你想在不使用gilly3方法的情况下使用私有变量,Near Privman的答案似乎是唯一真正的解决方案,因为Douglas Crockford解释了如何在这里创建私有变量:http://javascript.crockford.com/private.html
这会增加额外的javascript处理时间,因为它无法使用原型继承,并且每次都会使用资源来重新创建函数。
但是,如果每次创建的闭包非常小或者创建新实例的次数很少,则这可能不是一个非常明显的问题。为了尝试并充分利用这两个方面,您可以将使用私有变量(via delegation pattern)的大部分方法委派给每次都不会重新创建的静态函数。这会使下面显示的publicMethodThatUsesPrivateVariable
方法更小,这意味着每次重新创建时间应该更短。
var _privateStaticMethod = function(privateVariableValue, methodParameter) {
var result;
// Execute the lengthy javascript logic here ...
result = Math.ceil(privateVariableValue / 108);
result += 4815162342;
return result;
};
Backbone.View.extend({
initialize: function() {
var _privateVariable = 303;
this.publicMethodThatUsesPrivateVariable = function(methodParameter) {
// Only place as little logic as you can here outside of the private static method being used below
_privateVariable += 1;
return _privateStaticMethod(_privateVariable, methodParameter);
};
},
// ...
});
请注意,上面的代码也应包含在某种函数中,以便_privateStaticMethod
不是全局变量/函数。
答案 4 :(得分:0)
我很喜欢在接近Privman的答案,直到我遇到了一个超越&#34;超级&#34;的问题。方法。由于在构造Backbone对象之前不会调用initialize()
,所以在需要时(如果需要在调用initialize()
之前)可能不会发生覆盖。 / p>
特别是,这可能是parse()
的问题。 (对于视图来说不是问题,但对于集合和模型来说肯定不是。)鉴于此设置:
MyModel = Backbone.Model.extend({
initialize: function (options) {
this.parse = function (response, xhr) {
// parsing logic
};
// public & private vars/methods here
// and also initialize code
}
});
MySubModel = MyModel.extend({
initialize: function (options) {
this.parse = function (response, xhr) {
// override MyModel with my own parsing logic
}
// public & private vars/methods here
// and initialize code here
}
});
MySubModel.parse()
永远不会被召唤。
相反,我发现使用IIFE而不是initialize()都可以解决这个问题并且比使用已经具有指定目的的函数(initialize()
)更清晰双重责任作为定义其余阶级的闭包。
var MyModel = {};
(function () {
this.initialize = function (attributes, options) {
// initialize me
}
this.parse = function (response, xhr) {
// override at will
}
// other public & private vars/methods here
}).call(MyModel);
Backbone.Model.extend(MyModel);
不幸的是,这与&#34;私人&#34;有同样的问题。变量在类的所有实例中共享,gilly3和Near Privman的答案都是如此。很想听到让私有变量成为可能的非尴尬方式,但也许我应该放弃并认识到我现在正在编写JavaScript,而不是Java / AS3 / C ++。
答案 5 :(得分:0)
你可以试试这个:
var Thing = Backbone.Model.extend(
{
constructor : function ()
{
var _value = "Private data!";
this.getValue = function ()
{
console.log(_value);
};
this.setValue = function (value)
{
_value = value;
};
}
});
答案 6 :(得分:0)
添加“私有”变量的标准Backbone方法是将它们声明为带有下划线“_”的属性。它们并非真正私密,但开发人员会意识到它们并不是公开使用的。
事实上,这是Backbone如何存储自己的私有变量。
答案 7 :(得分:0)
在使用Broserify.js与Backbone(以及任何上述中型项目)的上下文中,我找到了以下方式来获得私有变量和函数:
myView.js
'use strict';
var config = require('../config.js'),
private_var = 'private variable',
my_private_fn = function() {
...
};
module.exports = Backbone.Model.extend({
initialize: function() {
this.my_public = 'public variable');
console.log('This is my' + this.my_public);
console.log('This is my' + my_private);
},
});
答案 8 :(得分:-2)
使用“这个”?
initialize:function () { this.viewpointers = {} }, render:function () { var self = this _.each(this.viewpointers, function(item){ self.$el.find(".assigned-items").append(item.render().el) }); }
添加它们。然后这些至少受到保护。
this.viewpointers[model.id] = new view({model:model})