如何在Javascript中创建静态变量?
当前回答
所以我从其他答案中看到的是,它们没有解决面向对象编程中静态属性的基本架构要求。
面向对象编程实际上有两种不同的风格,一种是基于类的(C++、C#、Java等),另一种是原型的(Javascript)。在基于类的语言中,“静态属性”应该与类关联,而不是与实例化对象关联。这个概念实际上在Javascript这样的原型语言中更为直观,因为您只需将属性指定为父原型的值即可。
function MyObject() {};
MyObject.prototype.staticAttribute = "some value";
并从从该构造函数实例化的每个对象访问它,就像这样。。。
var childObject1 = new MyObject(); // Instantiate a child object
var childObject2 = new MyObject(); // Instantiate another child object
console.log(childObject.staticAttribute); // Access the static Attribute from child 1
console.log(childObject.staticAttribute); // Access the static Attribute from child 2
现在,如果您继续更改MyObject.prototype.staticAttribute,则更改将级联到立即继承它的子对象。
然而,有一些“陷阱”可能会严重破坏此属性的“静态”特性,或者只留下安全漏洞。。。
首先,确保通过将构造函数封装在另一个函数(如jQuery ready方法)中,从全局命名空间中隐藏构造函数
$(document).ready(function () {
function MyObject() {
// some constructor instructions
};
MyObject.prototype.staticAttribute = "some value";
var childObject = new MyObject(); // instantiate child object
console.log(childObject.staticAttribute); // test attribute
});
第二,也是最后一点,即使您这样做,该属性仍然可以从您自己的脚本的任何其他部分进行编辑,因此可能是代码中的错误覆盖了某个子对象的属性,并将其从父原型分离,因此如果您更改父属性,它将不再级联并更改子对象的静态属性。看看这个jsfiddle。在不同的场景中,我们可以使用Object.freeze(obj)来停止对子对象的任何更改,也可以在构造函数中设置setter和getter方法并访问闭包,这两者都具有相关的复杂性。
在我看来,“静态属性”的基于类的思想和这个Javascript实现之间似乎没有完美的相似之处。因此,我认为从长远来看,使用一种对Javascript更友好的不同代码模式可能会更好。比如一个中央数据存储或缓存,甚至一个专用的帮助对象来保存所有必要的静态变量。
其他回答
除其他内容外,目前还有一个关于ECMA提案的草案(第2阶段提案),它在类中引入了静态公共字段。(考虑了私人领域)
使用提案中的示例,建议的静态语法如下所示:
class CustomDate {
// ...
static epoch = new CustomDate(0);
}
并等同于其他人强调的以下内容:
class CustomDate {
// ...
}
CustomDate.epoch = new CustomDate(0);
然后,您可以通过CustomDate.epoch访问它。
您可以在提案静态类特性中跟踪新提案。
目前,babel通过您可以使用的转换类财产插件支持此功能。此外,尽管仍在进行中,V8正在实现它。
在使用jQuery的MVC网站中,我希望确保某些事件处理程序中的AJAX操作只能在前一个请求完成后执行。我使用一个“静态”jqXHR对象变量来实现这一点。
按下以下按钮:
<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>
我通常使用这样的IIFE作为点击处理程序:
var ajaxAction = (function (jqXHR) {
return function (sender, args) {
if (!jqXHR || jqXHR.readyState == 0 || jqXHR.readyState == 4) {
jqXHR = $.ajax({
url: args.url,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify($(sender).closest('form').serialize()),
success: function (data) {
// Do something here with the data.
}
});
}
};
})(null);
还有另一种方法,它解决了我浏览这个线程后的需求。这完全取决于您想要使用“静态变量”实现什么。
全局属性sessionStorage或localStorage允许在会话的生命周期内存储数据,或在明确清除之前存储不确定的更长时间。这允许在页面/应用程序的所有窗口、框架、选项卡面板、弹出窗口等之间共享数据,并且比一个代码段中的简单“静态/全局变量”功能强大得多。
它避免了顶级全局变量(如Window.myglobal)的范围、生存期、语义、动态等方面的所有麻烦。不知道它有多高效,但这对于以适度速度访问的少量数据来说并不重要。
轻松访问为“sessionStorage.mydata=anything”,并以类似方式检索。看见“JavaScript:最终指南,第六版”,David Flanagan,ISBN:978-0-596-80552-4,第20章,第20.1节。通过简单的搜索,或在O’Reilly Safaribooks订阅(价值黄金)中,可以轻松下载为PDF格式。
我没有在任何答案中看到这个想法,所以只是将其添加到列表中。如果是重复的,请告诉我,我会删除它并对另一个进行投票。
我在我的网站上创建了一种超级全球化。由于每次页面加载时都会加载几个js文件,而其他几十个js文件只加载在一些页面上,所以我将所有“全局”函数都放在一个全局变量中。
在我第一个包含的“全局”文件的顶部是声明
var cgf = {}; // Custom global functions.
然后我删除了几个全局助手函数
cgf.formBehaviors = function()
{
// My form behaviors that get attached in every page load.
}
然后,如果我需要一个静态变量,我只需将其存储在范围之外,例如文档就绪或行为附件之外。(我使用jquery,但它应该在javascript中工作)
cgf.first = true;
$.on('click', '.my-button', function()
{
// Don't allow the user to press the submit twice.
if (cgf.first)
{
// first time behavior. such as submit
}
cgf.first = false;
}
这当然是一个全局的,而不是静态的,但由于它在每次加载页面时都会重新初始化,所以它可以达到相同的目的。
你可以这样想。在<body></body>中放置标记<p id=“静态变量”></p>并设置其可见性:隐藏。
当然,您可以使用jquery来管理前一个标记中的文本。实际上,这个标签成为你的静态变量。