Javascript:最终/不可变的全局variables?
我想我知道答案,但是…有什么办法来防止后来执行<script>
修改全局variables? 我知道全局variables首先是不好的,但是在必要的时候,有没有办法使它成为“最终”或“不可变的”? 黑客/创意解决scheme是受欢迎的。 谢谢
const关键字?
您可以使用闭包技术,MYGLOBALS是一个对象,该对象具有一个名为getValue的函数,针对除“MYGLOBALS”实例之外的所有内容的“全局variables”关联数组。
var MYGLOBALS = function() { var globals = { foo : "bar", batz : "blah" } return { getValue : function(s) { return globals[s]; } } }(); alert(MYGLOBALS.getValue("foo")); // returns "bar" alert(MYGLOBALS.getValue("notthere")); // returns undefined MYGLOBALS.globals["batz"] = 'hardeehar'; // this will throw an exception as it should
我知道这个问题是旧的,但你可以使用Object.freeze(yourGlobalObjectHere); 我刚刚在这里写了一篇关于它的博客文章。
是的,const在某些语言中是常量或最终的短语。 谷歌“JavaScriptvariables常量”或常量加倍,我甚至testing了自己,所以
const yourVar = 'your value';
那是你在找什么。
这将是更清洁的方法
var CONSTANTS = function() { var constants = { } ; //Initialize Global Space Here return { defineConstant: function(name,value) { if(constants[name]) { throw "Redeclaration of constant Not Allowed"; } }, getValue(name) { return constants[name]; } } ; }() ; CONSTANTS.defineConstant('FOO','bar') ; console.log(CONSTANTS.getValue('FOO')) ; //Returns bar CONSTANTS.defineConstant('FOO','xyz') ; // throws exception as constant already defined CONSTANTS.getValue('XYZ') ; //returns undefined
select一个不太可能被意外覆盖的variables名,并相信程序员不会做愚蠢的事情。 JavaScript不是Java,所以不要假装它是。
另外,如果你真正想做的是命名空间,使用一个自我执行的函数文字:
var myLibName = (function() { var aPrivateVar; function aPrivateFunction() {} function accessorForPrivateVar() { return aPrivateVar; } // public interface: return { getPrivateVar : accessorForPrivateVar } })();
尝试这个:
const whatEver = 'Hello World!!!'; function foo(value){ whatEver = value; }
那么你会这样称呼它…
<div onclick="foo('New Value');">Change Me First</div> <div onclick="alert(whatEver);">Then click me After: Should Be alert "Hello World!!!"</div>
那么这个代码是由http://ejohn.org/ @ http://ejohn.org/blog/ecmascript-5-objects-and-properties/
看起来这个实际上是有效的…我运行一些“小”testing并冻结variables和属性。
冻结一个物体是locking的最终forms。 一旦物体被冻结,它就不能被解冻,也不能以任何方式被篡改。 这是最好的方法来确保您的对象将保持完全一样,因为你无限期地离开他们。
Object.freeze = function( obj ) { var props = Object.getOwnPropertyNames( obj ); for ( var i = 0; i < props.length; i++ ) { var desc = Object.getOwnPropertyDescriptor( obj, props[i] ); if ( "value" in desc ) { desc.writable = false; } desc.configurable = false; Object.defineProperty( obj, props[i], desc ); } return Object.preventExtensions( obj ); };
小例子
var config = (function (__name) { name: __name var _local = { Server: "SomeText", ServerDate: "SomeServerDate", JSDate : Util.today(), User : { user: "1stUser", name: "", email: "" }, } /*Private Methods*/ function freezing(__array) { $.each(__array, function (_index, _item) { Object.freeze(_item); }); } /*Public Methods*/ var $r = {}; $r.info = function () { return _local; } freezing([ _local, _local.User ]); _local.User.user = "newUser"; //Trying to assing new value //Remain with the same value as first declaration console.log(_local.User.user); //--> "1stUser" return $r; })("config");
公约和良好的文件。
你可以用两个(或多个)下划线在你的“不可变”variables前面加上下划线,以表明这个东西不是被其他人使用的,并且可以避免其他人的variables与你的variables相冲突。
也许像__GLOBALNAMESPACE
(丑陋的名字,我知道)创build一个'命名空间',然后添加您的variables(例如__GLOBALNAMESPACE.my_var
),并创build一个像这样的方法来检索它们:
getVariable(string name){ return __GLOBALNAMESPACE[name] }
只是我2美分。
你可能想试试这个jQuery插件 。 它阻止你在javascript中创build全局对象:)
示例代码
存储数据
// 'val' can be a string, integer, hash table, array, object $.secret( 'in', 'secretName', val ); // or a function $.secret( 'in', 'secretName', function( arg1, arg2, arg3 ){ // do something here });
使用数据; 你甚至可以在不同的文件中使用它。
var lang = $.secret( 'out', 'lang' );
调用一个函数
$.secret( 'call', 'secretName', [ arg1, arg2, arg3 ]); // or $.secret( 'call', 'secretName', arg );
清除数据
$.secret( 'clear', 'lang' );
源代码在github上
Javascript是面向对象的,而不是制作variables$ public static ,考虑把它设置为private,然后正确地提供一个获取方法,但不能设置它。
例如
private var myGlobal : myType; function GetMyGlobal() : myType { return myGlobal; }
有十种不同的方式来解决任何问题,你的方式和正确的方式。
Object.defineProperty(window, 'CONSTANT_NAME', {value: CONSTANT_VALUE}); // usage console.log(CONSTANT_NAME);
Object.defineProperty()
用下列默认属性创build一个属性:
-
当且仅当该属性描述符的types可能被改变,并且该属性可能从相应的对象中被删除时才可configuration。 默认为false。
-
enumerable
当且仅当此属性在枚举相应对象上的属性时显示。 默认为false。 -
当且仅当与属性相关联的值可能被赋值运算符改变时才为真。 默认为false。
如果“常量”是一个对象,你可能还想通过冻结来使它不可变。 obj =
Object.freeze(obj)
。 请记住,子物件对象不会自动冻结。
而不是在全局范围内声明所有这些variables,你可以有一个全局对象环绕这些variables。 使用Object.defineProperty()
和/或Object.defineProperties()
将writable
标志设置为false
,可以有一个不可变的variables。
var myObj = {}; Object.defineProperty(myObj, 'myVar', { value: someValue, writable: false });
或者你可以使用const关键字
const MY_VAR = 10;
如果可以使用打字稿,则可以将属性标记为readonly
从来没听说过。 我能想到的最好的方法就是将值存储在一个不太可能被修改的对象上。
例如
navigator.pleaseDontChangeThis = 25;
它仍然可以改变,但最正常的JS将不需要设置/更改导航器对象上的任何值。 我个人使用它来存储一个唯一的生成的ID。 😉