javascript 主干视图的私有和公共变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7575630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Private and public variables to a backbone view
提问by Chapsterj
In a backbone view where would you put your private variables and your public.
在主干视图中,您会将私有变量和公共变量放在哪里。
Right now I have something like this:
现在我有这样的事情:
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
}
});
I tried adding a var myPrivate
before the initialize method but it threw an error. Where would private variables that are only used within the view go?
我尝试var myPrivate
在 initialize 方法之前添加一个,但它抛出了一个错误。仅在视图中使用的私有变量会去哪里?
回答by Near Privman
I suggest you use the initialize method as a closure around all other methods. I think this will give you behaviour more consistent with what we get in classical inheritance languages like C++ and Java:
我建议您使用 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; } }; } });
回答by gilly3
Wrap it all up in a self-invoking anonymous function:
将其全部封装在一个自调用匿名函数中:
(function() {
var myPrivate = 1;
myView = Backbone.View.extend({
initialize: function(options){
this.myPublic = "I'm public";
myPrivate++;
},
render: function() {
alert(myPrivate);
}
});
})();
Edit:As pointed out in kaustubh's commentbelow, the above example creates a private variable that is shared among the instances. You could create a sort of protectedvariable, that is, an instance level variable that could be read by other instances of the View. Give each instance a unique public id and store instance variables in a "private static" variable. Then access the variables by instance id:
编辑:正如下面kaustubh 的评论所指出的,上面的例子创建了一个在实例之间共享的私有变量。您可以创建一种受保护的变量,即可以由 View 的其他实例读取的实例级变量。给每个实例一个唯一的公共 ID,并将实例变量存储在“私有静态”变量中。然后通过实例 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)
}
});
})();
Or, you can do it without using a public id, but it becomes a bit more convoluted:
或者,您可以在不使用公共 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)
}
});
})();
I'm struggling to come up with a way of storing truly private variables. I'll post back if inspiration strikes.
我正在努力想出一种存储真正私有变量的方法。如果灵感来了,我会回帖。
回答by jgroenen
Instead of inserting the object directly into the extend function, how about creating a closure and from that closure return an object to the extend function?
与其将对象直接插入到扩展函数中,不如创建一个闭包并从该闭包中将对象返回给扩展函数呢?
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);
}
};
} ());
I haven't tried this, because I have no Backbone install available right now.
我还没有尝试过这个,因为我现在没有可用的 Backbone 安装。
回答by ericsoco
I was liking Near Privman's answer until I ran into a problem with overriding a "super" method. As initialize()
isn't called until some way through the construction of a Backbone object, overriding may not have happened by the time it needs to (if it needs to before initialize()
is called).
我很喜欢 Near Privman 的回答,直到我遇到了覆盖“超级”方法的问题。由于initialize()
在构建 Backbone 对象的某个过程中才被调用,因此在需要时(如果需要在initialize()
调用之前)覆盖可能还没有发生。
In particular, this can be a problem with parse()
. (Not an issue for Views, but definitely for Collections and Models.) Given this setup:
特别是,这可能是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()
will never be called.
MySubModel.parse()
永远不会被调用。
Instead, I've found that using an IIFEinstead of initialize() both clears up this problem and reads cleaner than making a function that already has a specified purpose (initialize()
) do double duty as a closure for defining the rest of the class.
相反,我发现使用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);
Unfortunately, this has the same problem with "private" variables being shared across all instances of the class as do both gilly3 and Near Privman's answers. Would love to hear a non-awkward way to make private variables possible, but maybe I should just give it up and recognize I'm writing JavaScript now, not Java/AS3/C++.
不幸的是,这与在类的所有实例之间共享的“私有”变量存在相同的问题,就像 Gilly3 和 Near Privman 的答案一样。很想听到一种使私有变量成为可能的非尴尬方式,但也许我应该放弃它并认识到我现在正在编写 JavaScript,而不是 Java/AS3/C++。
回答by Marble Daemon
You can try this:
你可以试试这个:
var Thing = Backbone.Model.extend(
{
constructor : function ()
{
var _value = "Private data!";
this.getValue = function ()
{
console.log(_value);
};
this.setValue = function (value)
{
_value = value;
};
}
});
回答by Donald Taylor
The standard Backbone way of adding "private" variables is to declare them as attributes with an underscore "_" before them. They are not really private, but developers will realize that they are not meant to be publicly used.
添加“私有”变量的标准 Backbone 方法是将它们声明为在它们之前带有下划线“_”的属性。它们并不是真正私有的,但开发人员会意识到它们并不打算公开使用。
This, in fact, is how Backbone stores its own private variables.
实际上,这就是 Backbone 存储自己的私有变量的方式。
回答by Claudiu
In the context of using Broserify.jswith Backbone (and really any above medium project) I found the following way to have private vars and functions:
在将Broserify.js与 Backbone(以及任何上述中型项目)一起使用的上下文中,我发现了以下方法来拥有私有变量和函数:
myView.js
我的视图.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);
},
});
回答by Steven
gilly3's solution may be the best answer, although it is not technically creating/using a private variable because other instances of the same closure will have access to it (you probably are not as concerned about other members of your development team misusing that privilege, but it could happen).
gilly3 的解决方案可能是最好的答案,尽管它在技术上没有创建/使用私有变量,因为同一闭包的其他实例可以访问它(您可能并不担心开发团队的其他成员滥用该特权,但是它可能发生)。
If you want to use private variables without using gilly3's approach, Near Privman's answer appears to be the only true solution as Douglas Crockford explains how to create private variables here: http://javascript.crockford.com/private.html
如果您想在不使用 Gilly3 方法的情况下使用私有变量,则 Near Privman 的答案似乎是唯一正确的解决方案,因为 Douglas Crockford 在此处解释了如何创建私有变量:http: //javascript.crockford.com/private.html
This will add additional javascript processing time since it will not be able to make use of prototypal inheritance and will be using resources to recreate the function each time.
这将增加额外的 javascript 处理时间,因为它将无法利用原型继承,并且每次都将使用资源来重新创建函数。
However, this may not be a very noticeable issue if the closure you create each time is very small or if the number of times a new instance is created is minimal. In an effort to try and get the best of both worlds, you can delegate the bulk of your method that uses the private variable (via delegation pattern) to a static function that won't get recreated each time. This will leave your publicMethodThatUsesPrivateVariable
method shown below smaller, which means that it should take less time to recreate each time.
但是,如果您每次创建的闭包非常小或者创建新实例的次数很少,这可能不是一个非常明显的问题。为了尝试两全其美,您可以将使用私有变量的大部分方法(通过委托模式)委托给不会每次都重新创建的静态函数。这将使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);
};
},
// ...
});
Note that the code above should be wrapped in some kind of function as well so that _privateStaticMethod
is not a global variable/function.
请注意,上面的代码也应该包含在某种函数中,这样它就_privateStaticMethod
不是全局变量/函数。
回答by zzz
Using "this"?
用“这个”?
initialize:function () { this.viewpointers = {} }, render:function () { var self = this _.each(this.viewpointers, function(item){ self.$el.find(".assigned-items").append(item.render().el) }); }
adding them. Then these are protected atleast.
添加它们。那么这些至少受到保护。
this.viewpointers[model.id] = new view({model:model})