如何在Javascript中创建静态变量?
当前回答
我已经看到了一些类似的答案,但我想提到这篇文章描述得最好,所以我想和大家分享一下。
下面是从中提取的一些代码,我已经对其进行了修改,以获得一个完整的示例,这有望为社区带来好处,因为它可以用作类的设计模板。
它还回答了您的问题:
function Podcast() {
// private variables
var _somePrivateVariable = 123;
// object properties (read/write)
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
// for read access to _somePrivateVariable via immutableProp
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
在该示例中,您可以按如下方式访问静态财产/函数:
// access static properties/functions
console.log(Podcast.FILE_EXTENSION); // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
对象财产/功能如下:
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
注意,在podcast.immutableProp()中,我们有一个闭包:对_somePrivateVariable的引用保留在函数中。
您甚至可以定义getter和setter。看看下面的代码段(其中d是要为其声明属性的对象原型,y是构造函数外部不可见的私有变量):
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {return this.getFullYear() },
set: function(y) { this.setFullYear(y) }
});
它通过get和set函数定义属性d.year-如果未指定set,则该属性是只读的,无法修改(请注意,如果尝试设置该属性,则不会出现错误,但没有任何效果)。每个属性都具有可写、可配置(允许在声明后更改)和可枚举(允许将其用作枚举器)的属性,这些属性默认为false。您可以通过第三个参数中的defineProperty设置它们,例如enumerable:true。
同样有效的是以下语法:
// getters and setters - alternative syntax
var obj = { a: 7,
get b() {return this.a + 1;},
set c(x) {this.a = x / 2}
};
它定义了可读/可写属性a、只读属性b和只读属性c,通过这些属性可以访问属性a。
用法:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
笔记:
为了避免在忘记新关键字时出现意外行为,我建议您在函数Podcast中添加以下内容:
// instantiation helper
function Podcast() {
if(false === (this instanceof Podcast)) {
return new Podcast();
}
// [... same as above ...]
};
现在,以下两个实例化都将按预期工作:
var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast(); // you can omit the new keyword because of the helper
“new”语句创建一个新对象并复制所有财产和方法,即。
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
还要注意,在某些情况下,使用构造函数Podcast中的return语句返回一个自定义对象保护类内部依赖但需要公开的函数可能会很有用。这将在本系列文章的第2章(对象)中进一步解释。
你可以说a和b继承自播客。现在,如果您想在Podcast中添加一个方法,该方法在a和b安装后适用于所有的Podcast,该怎么办?在这种情况下,使用.prototype如下:
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
现在再次调用a和b:
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
您可以在这里找到有关原型的更多详细信息。如果你想做更多的继承,我建议你研究一下。
强烈建议阅读我上面提到的系列文章,其中还包括以下主题:
功能物体原型对构造函数强制执行新吊起自动插入分号静态财产和方法
请注意,JavaScript的自动分号插入“特性”(如6.中所述)通常会导致代码中出现奇怪的问题。因此,我宁愿将其视为一个bug而不是一个特性。
如果您想阅读更多,这里有一篇关于这些主题的MSDN文章,其中一些描述提供了更多细节。
阅读MDN JavaScript指南中的文章也很有趣(也涵盖了上述主题):
JavaScript简介使用对象
如果您想知道如何在JavaScript中模拟c#out参数(如DateTime.TryParse(str,out result)),可以在这里找到示例代码。
使用IE的人(除非使用F12打开开发人员工具并打开控制台选项卡,否则IE没有JavaScript控制台)可能会发现以下代码片段很有用。它允许您使用console.log(msg);如在上述示例中所使用的。只需将其插入播客功能之前。
为了方便起见,下面是上面一个完整的代码片段中的代码:
让控制台={log:function(msg){let canvas=document.getElementById(“log”),br=canvas.innerHTML==“”?“”:“<br/>”;canvas.innerHTML+=(br+(msg||“”).toString());}};console.log('有关详细信息,请参阅解释文本');函数播客(){//使用此选项,您可以在没有新建的情况下进行实例化(请参阅文本中的描述)if(false==(播客的这个实例)){return new播客();}//私有变量var_somePrivateVariable=123;//对象财产this.title='天文学演员';this.description='基于事实的银河之旅';this.link='http://www.astronomycast.com';this.immutableProp=函数(){return _somePrivateVariable;}//目标函数this.toString=函数(){return'标题:'+this.Title;}};//静态特性播客.FILE_EXTENSION=“mp3”;//静态函数Podcast.download=函数(播客){console.log(“下载”+播客+“…”);};//访问静态财产/函数播客.FILE_EXTENSION;//'mp3'播客.下载('天文学广播');//'正在下载天文学演员…'//访问对象财产/函数var podcast=新播客();podcast.title=“辛普森一家”;console.log(podcast.toString());//标题:《辛普森一家》console.log(podco.immutableProp());//123//吸气器和settervar d=日期.协议类型;Object.defineProperty(d,“年”{获取:函数(){return this.getFullYear()},集合:函数(y){this.setFullYear(y)}});//getters和setters-替代语法变量obj={a: 7中,获取b(){返回此.a+1;},集合c(x){这个.a=x/2}};//用法:控制台日志(obj.a);console.log(obj.b);//输出:7,8物镜c=40;控制台日志(obj.a);console.log(obj.b);//输出:20,21var a=新播客();var b=新播客();a.title=“a”;b.title=“An”+b.title;console.log(a.title);//“a”console.log(b.title);//“天文学演员”Podcast.prototype.titleAndLink=函数(){return this.title+“[”+this.link+“]”;};console.log(a.titleAndLink());//“一个[http://www.astronomycast.com]"console.log(b.titleAndLink());//“天文学演员[http://www.astronomycast.com]"<div id=“log”></div>
笔记:
在这里(JavaScript最佳实践)和那里(“var”与“let”)都可以找到关于JavaScript编程的一些好的提示、提示和建议。还推荐这篇关于隐式类型转换(强制)的文章。使用类并将其编译为JavaScript的一种方便方法是TypeScript。这里是一个游乐场,你可以在那里找到一些例子,告诉你它是如何工作的。即使您目前没有使用TypeScript,也可以查看一下,因为您可以在并排视图中将TypeScript与JavaScript结果进行比较。大多数示例都很简单,但也有一个光线跟踪器示例,您可以立即尝试。我建议特别关注“使用类”、“使用继承”和“使用泛型”示例,方法是在组合框中选择它们-这些都是很好的模板,可以立即在JavaScript中使用。字体与Angular一起使用。为了在JavaScript中实现本地变量、函数等的封装,我建议使用如下模式(JQuery使用相同的技术):
<html><head></head><body><脚本>“使用严格”;//模块模式(自调用函数)const myModule=(函数(上下文){//要允许替换函数,请使用“var”,否则保留“const”//将变量和函数与本地模块范围放在此处:var print=函数(str){if(str!==undefined)context.document.write(str);context.document.write(“<br/><br/>”);回来}// ... 更多变量。。。//主要方法var _main=函数(标题){if(title!==未定义)打印(title);打印(“<b>上次修改时间:</b>”+context.document.lastModified+“<br/>”);// ... 更多代码。。。}//公共方法返回{主:_Main// ... 更多公共方法、财产。。。};})(本);//使用模块myModule.Main(“<b>模块演示</b>”);</script></body></html>
当然,您可以也应该将脚本代码放在一个单独的*.js文件中;这只是为了保持示例简短而内联编写的。
这里更详细地描述了自调用函数(也称为IIFE=立即调用函数表达式)。
其他回答
function Person(){
if(Person.count == undefined){
Person.count = 1;
}
else{
Person.count ++;
}
console.log(Person.count);
}
var p1 = new Person();
var p2 = new Person();
var p3 = new Person();
在JavaScript中,任何东西都是原始类型或对象。函数是对象-(键值对)。
创建函数时,将创建两个对象。一个对象表示函数本身,另一个对象代表函数的原型。
从这个意义上讲,函数基本上是一个具有财产的对象:
function name,
arguments length
and the functional prototype.
因此,在何处设置静态属性:两个位置,要么在函数对象内部,要么在功能原型对象内部。
这里有一个代码片段,它使用新的JavaScript关键字创建了两个实例。
函数C(){//函数var privateProperty=“42”;this.publicProperty=“39”;this.privateMethod=函数(){console.log(privateProperty);};}C.prototype.publicMethod=函数(){console.log(this.publicProperty);};C.prototype.staticPrototypeProperty=“4”;C.staticProperty=“3”;var i1=新C();//实例1var i2=新C();//实例2i1.privateMethod();i1.publicMethod();console.log(i1.__proto__.staticPrototypeProperty);i1.__proto__.staticPrototypeProperty=“2”;console.log(i2.__proto__.staticPrototypeProperty);console.log(i1.__proto__constructor.staticProperty);i1.__proto__constructor.staticProperty=“9”;console.log(i2.__proto__constructor.staticProperty);
主要思想是实例i1和i2使用相同的静态财产。
更新答案:
在ECMAScript 6中,可以使用static关键字创建静态函数:
class Foo {
static bar() {return 'I am static.'}
}
//`bar` is a property of the class
Foo.bar() // returns 'I am static.'
//`bar` is not a property of instances of the class
var foo = new Foo()
foo.bar() //-> throws TypeError
ES6类没有为静态引入任何新的语义。您可以在ES5中这样做:
//constructor
var Foo = function() {}
Foo.bar = function() {
return 'I am static.'
}
Foo.bar() // returns 'I am static.'
var foo = new Foo()
foo.bar() // throws TypeError
您可以指定Foo的属性,因为在JavaScript中,函数是对象。
你可以这样想。在<body></body>中放置标记<p id=“静态变量”></p>并设置其可见性:隐藏。
当然,您可以使用jquery来管理前一个标记中的文本。实际上,这个标签成为你的静态变量。
您可以使用arguments.callee存储“静态”变量(这在匿名函数中也很有用):
function () {
arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
arguments.callee.myStaticVar++;
alert(arguments.callee.myStaticVar);
}
推荐文章
- 右击是Javascript事件吗?
- 如何找到JavaScript数组中包含的最大数字?
- 在数组中获取所有选中的复选框
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;