JavaScript中有常量吗?

2020/09/18 11:31 · javascript ·  · 0评论

有没有办法在JavaScript中使用常量

如果没有,指定用作常量的变量的常用惯例是什么?

ES2015开始,JavaScript的概念是const

const MY_CONSTANT = "some-value";

几乎可以在除IE 8、9和10之外的所有浏览器中使用有些可能还需要启用严格模式

您可以var与ALL_CAPS之类的约定一起使用,以表明如果需要支持旧版浏览器或正在使用旧版代码,则不应修改某些值:

var MY_CONSTANT = "some-value";

您是否要保护变量不被修改?如果是这样,则可以使用模块模式:

var CONFIG = (function() {
     var private = {
         'MY_CONST': '1',
         'ANOTHER_CONST': '2'
     };

     return {
        get: function(name) { return private[name]; }
    };
})();

alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.MY_CONST = '2';
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.private.MY_CONST = '2';                 // error
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

使用这种方法,无法修改值。但是,您必须在CONFIG :(上使用get()方法。

如果您不需要严格保护变量值,则按照建议的方式操作并使用ALL CAPS的约定。

const关键字是ECMAScript的第6条草案,但迄今只享受的浏览器支持一知半解:http://kangax.github.io/compat-table/es6/语法为:

const CONSTANT_NAME = 0;
"use strict";

var constants = Object.freeze({
    "π": 3.141592653589793 ,
    "e": 2.718281828459045 ,
    "i": Math.sqrt(-1)
});

constants.π;        // -> 3.141592653589793
constants = 3;    // -> TypeError: Cannot assign to read only property 'π' …
constants.π;        // -> 3.141592653589793

delete constants.π; // -> TypeError: Unable to delete property.
constants.π;        // -> 3.141592653589793

参见Object.freeze如果您还希望将引用设为只读,可以使用constconstants

IE确实支持常量,例如:

<script language="VBScript">
 Const IE_CONST = True
</script>
<script type="text/javascript">
 if (typeof TEST_CONST == 'undefined') {
    const IE_CONST = false;
 }
 alert(IE_CONST);
</script>

ECMAScript 5确实引入了Object.defineProperty

Object.defineProperty (window,'CONSTANT',{ value : 5, writable: false });

每个现代浏览器(以及IE≥9)都支持

另请参见:ES5中的Object.defineProperty?

不,不是一般。Firefox实现了,const但我知道IE没有。


@John指出了一种在其他语言上已经使用多年的const命名惯例,我认为没有理由不能使用它。当然,这并不意味着某人无论如何也不会覆盖变量的值。:)

在JavaScript中,我的首选是使用函数返回常量值。

function MY_CONSTANT() {
   return "some-value";
}


alert(MY_CONSTANT());

Mozillas MDN Web文档包含有关的良好示例和说明const摘抄:

// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;

// this will throw an error - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;

但是可悲的是IE9 / 10仍然不支持const和它荒谬的原因

那么,IE9对const做了什么?到目前为止,我们的决定是不支持它。由于尚未在所有浏览器上使用,因此它尚未成为共识功能。

...

最后,似乎最好的长期网络解决方案是将其保留,并等待标准化过程正常进行。

他们没有实现它,因为其他浏览器没有正确实现它?太害怕使它变得更好?是否定义标准,常量是常量:设置一次,永不更改。

和所有想法:每个功能都可以被覆盖(XSS等)。因此,var或中没有区别function(){return}const是唯一的实常数。

更新:IE11 支持 const

IE11包括用于新兴的ECMAScript 6标准的明确定义和常用的功能,包括让,支承constMapSet,和WeakMap,以及__proto__改进的互操作性。

如果您不介意使用函数:

var constant = function(val) {
   return function() {
        return val;
    }
}

这种方法为您提供函数而不是常规变量,但可以保证*设置后没有人可以更改该值。

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

我个人觉得这很令人愉快,特别是在从可观察的观测值适应了这种模式之后。

*除非有人constant在您调用它之前重新定义了该函数

使用“新”对象api,您可以执行以下操作:

var obj = {};
Object.defineProperty(obj, 'CONSTANT', {
  configurable: false
  enumerable: true,
  writable: false,
  value: "your constant value"
});

看看对Mozilla的MDN的更多细节。它不是第一级变量,因为它是附加到对象的,但是如果有作用域,则可以将其附加到对象。this应该也可以。因此,例如在全局范围内执行此操作将在窗口上声明一个伪常量值(这是一个非常糟糕的主意,您不应随意声明全局变量)

Object.defineProperty(this, 'constant', {
  enumerable: true, 
  writable: false, 
  value: 7, 
  configurable: false
});

> constant
=> 7
> constant = 5
=> 7

注意:赋值将返回控制台中的赋值,但变量的值不会改变

在可能的情况下将常量分组为结构:

例如,在我当前的游戏项目中,我使用以下方法:

var CONST_WILD_TYPES = {
    REGULAR: 'REGULAR',
    EXPANDING: 'EXPANDING',
    STICKY: 'STICKY',
    SHIFTING: 'SHIFTING'
};

分配:

var wildType = CONST_WILD_TYPES.REGULAR;

比较:

if (wildType === CONST_WILD_TYPES.REGULAR) {
    // do something here
}

为了比较,我最近在使用:

switch (wildType) {
    case CONST_WILD_TYPES.REGULAR:
        // do something here
        break;
    case CONST_WILD_TYPES.EXPANDING:
        // do something here
        break;
}

IE11带有带有“ const”声明的新ES6标准。

以上内容适用于IE8,IE9和IE10等较早的浏览器。

您可以轻松地为脚本配备常量机制,该常量可以设置但不能更改。尝试更改它们会产生错误。

/* author Keith Evetts 2009 License: LGPL  
anonymous function sets up:  
global function SETCONST (String name, mixed value)  
global function CONST (String name)  
constants once set may not be altered - console error is generated  
they are retrieved as CONST(name)  
the object holding the constants is private and cannot be accessed from the outer script directly, only through the setter and getter provided  
*/

(function(){  
  var constants = {};  
  self.SETCONST = function(name,value) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if (!value) { throw new Error(' no value supplied for constant ' + name); }  
      else if ((name in constants) ) { throw new Error('constant ' + name + ' is already defined'); }   
      else {   
          constants[name] = value;   
          return true;  
    }    
  };  
  self.CONST = function(name) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if ( name in constants ) { return constants[name]; }    
      else { throw new Error('constant ' + name + ' has not been defined'); }  
  };  
}())  


// -------------  demo ----------------------------  
SETCONST( 'VAT', 0.175 );  
alert( CONST('VAT') );


//try to alter the value of VAT  
try{  
  SETCONST( 'VAT', 0.22 );  
} catch ( exc )  {  
   alert (exc.message);  
}  
//check old value of VAT remains  
alert( CONST('VAT') );  


// try to get at constants object directly  
constants['DODO'] = "dead bird";  // error  

忘记IE并使用const关键字。

但是,尚无精确的跨浏览器预​​定义方法来执行此操作,您可以通过控制变量的范围来实现它,如其他答案所示。

但是我建议使用命名空间来区别其他变量。这会将与其他变量发生碰撞的机率降到最低。

正确的命名空间,例如

var iw_constant={
     name:'sudhanshu',
     age:'23'
     //all varibale come like this
}

所以在使用这将是iw_constant.nameiw_constant.age

您还可以使用Object.freeze方法阻止在iw_constant内部添加任何新键或更改任何键。但是,旧版浏览器不支持它。

例如:

Object.freeze(iw_constant);

对于较旧的浏览器,您可以使用polyfill进行冻结。


如果您可以调用函数,则以下是定义常量的最佳跨浏览器方式。在自执行函数中为对象定义范围,并为常量ex返回一个get函数,例如:

var iw_constant= (function(){
       var allConstant={
             name:'sudhanshu',
             age:'23'
             //all varibale come like this

       };

       return function(key){
          allConstant[key];
       }
    };

//使用iw_constant('name')获取值
iw_constant('age')


**在两个示例中,您都必须非常小心地使用名称间距,以免对象或函数被其他库替换(如果对象或函数本身将被替换,则整个常量将消失)

有一阵子,我在传递给with()语句的对象常量中指定了“常量”(实际上并不是常量)我以为它很聪明。这是一个例子:

with ({
    MY_CONST : 'some really important value'
}) {
    alert(MY_CONST);
}

过去,我还创建了一个CONST命名空间,将所有常量放入其中。再次,与开销。嘘。

现在,我只是var MY_CONST = 'whatever';KISS

我的意见(仅适用于对象)。

var constants = (function(){
  var a = 9;

  //GLOBAL CONSTANT (through "return")
  window.__defineGetter__("GCONST", function(){
    return a;
  });

  //LOCAL CONSTANT
  return {
    get CONST(){
      return a;
    }
  }
})();

constants.CONST = 8; //9
alert(constants.CONST); //9

尝试!但是请理解-这是对象,而不是简单的变量。

也尝试:

const a = 9;

我也有这个问题。在寻找答案并查看每个人的所有回答之后,我想我已经找到了一个可行的解决方案。

看来,我遇到的大多数答案都是使用函数来保存常量。正如许多论坛的许多用户所张贴的那样,客户端的用户可以很容易地覆盖这些功能。基思·埃维茨(Keith Evetts)的回答使我很感兴趣,因为常量对象不能由外部访问,而只能从内部函数访问。

所以我想出了这个解决方案:

将所有内容放入匿名函数中,以使客户端无法更改变量,对象等。通过让其他函数从内部调用“真实”函数,还可以隐藏“真实”函数。我还想到了使用函数来检查客户端上的用户是否更改了函数。如果功能已更改,请使用内部“受保护”且无法更改的变量将其改回。

/*Tested in: IE 9.0.8; Firefox 14.0.1; Chrome 20.0.1180.60 m; Not Tested in Safari*/

(function(){
  /*The two functions _define and _access are from Keith Evetts 2009 License: LGPL (SETCONST and CONST).
    They're the same just as he did them, the only things I changed are the variable names and the text
    of the error messages.
  */

  //object literal to hold the constants
  var j = {};

  /*Global function _define(String h, mixed m). I named it define to mimic the way PHP 'defines' constants.
    The argument 'h' is the name of the const and has to be a string, 'm' is the value of the const and has
    to exist. If there is already a property with the same name in the object holder, then we throw an error.
    If not, we add the property and set the value to it. This is a 'hidden' function and the user doesn't
    see any of your coding call this function. You call the _makeDef() in your code and that function calls
    this function.    -    You can change the error messages to whatever you want them to say.
  */
  self._define = function(h,m) {
      if (typeof h !== 'string') { throw new Error('I don\'t know what to do.'); }
      if (!m) { throw new Error('I don\'t know what to do.'); }
      else if ((h in j) ) { throw new Error('We have a problem!'); }
      else {
          j[h] = m;
          return true;
    }
  };

  /*Global function _makeDef(String t, mixed y). I named it makeDef because we 'make the define' with this
    function. The argument 't' is the name of the const and doesn't need to be all caps because I set it
    to upper case within the function, 'y' is the value of the value of the const and has to exist. I
    make different variables to make it harder for a user to figure out whats going on. We then call the
    _define function with the two new variables. You call this function in your code to set the constant.
    You can change the error message to whatever you want it to say.
  */
  self._makeDef = function(t, y) {
      if(!y) { throw new Error('I don\'t know what to do.'); return false; }
      q = t.toUpperCase();
      w = y;
      _define(q, w);
  };

  /*Global function _getDef(String s). I named it getDef because we 'get the define' with this function. The
    argument 's' is the name of the const and doesn't need to be all capse because I set it to upper case
    within the function. I make a different variable to make it harder for a user to figure out whats going
    on. The function returns the _access function call. I pass the new variable and the original string
    along to the _access function. I do this because if a user is trying to get the value of something, if
    there is an error the argument doesn't get displayed with upper case in the error message. You call this
    function in your code to get the constant.
  */
  self._getDef = function(s) {
      z = s.toUpperCase();
      return _access(z, s);
  };

  /*Global function _access(String g, String f). I named it access because we 'access' the constant through
    this function. The argument 'g' is the name of the const and its all upper case, 'f' is also the name
    of the const, but its the original string that was passed to the _getDef() function. If there is an
    error, the original string, 'f', is displayed. This makes it harder for a user to figure out how the
    constants are being stored. If there is a property with the same name in the object holder, we return
    the constant value. If not, we check if the 'f' variable exists, if not, set it to the value of 'g' and
    throw an error. This is a 'hidden' function and the user doesn't see any of your coding call this
    function. You call the _getDef() function in your code and that function calls this function.
    You can change the error messages to whatever you want them to say.
  */
  self._access = function(g, f) {
      if (typeof g !== 'string') { throw new Error('I don\'t know what to do.'); }
      if ( g in j ) { return j[g]; }
      else { if(!f) { f = g; } throw new Error('I don\'t know what to do. I have no idea what \''+f+'\' is.'); }
  };

  /*The four variables below are private and cannot be accessed from the outside script except for the
    functions inside this anonymous function. These variables are strings of the four above functions and
    will be used by the all-dreaded eval() function to set them back to their original if any of them should
    be changed by a user trying to hack your code.
  */
  var _define_func_string = "function(h,m) {"+"      if (typeof h !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if (!m) { throw new Error('I don\\'t know what to do.'); }"+"      else if ((h in j) ) { throw new Error('We have a problem!'); }"+"      else {"+"          j[h] = m;"+"          return true;"+"    }"+"  }";
  var _makeDef_func_string = "function(t, y) {"+"      if(!y) { throw new Error('I don\\'t know what to do.'); return false; }"+"      q = t.toUpperCase();"+"      w = y;"+"      _define(q, w);"+"  }";
  var _getDef_func_string = "function(s) {"+"      z = s.toUpperCase();"+"      return _access(z, s);"+"  }";
  var _access_func_string = "function(g, f) {"+"      if (typeof g !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if ( g in j ) { return j[g]; }"+"      else { if(!f) { f = g; } throw new Error('I don\\'t know what to do. I have no idea what \\''+f+'\\' is.'); }"+"  }";

  /*Global function _doFunctionCheck(String u). I named it doFunctionCheck because we're 'checking the functions'
    The argument 'u' is the name of any of the four above function names you want to check. This function will
    check if a specific line of code is inside a given function. If it is, then we do nothing, if not, then
    we use the eval() function to set the function back to its original coding using the function string
    variables above. This function will also throw an error depending upon the doError variable being set to true
    This is a 'hidden' function and the user doesn't see any of your coding call this function. You call the
    doCodeCheck() function and that function calls this function.    -    You can change the error messages to
    whatever you want them to say.
  */
  self._doFunctionCheck = function(u) {
      var errMsg = 'We have a BIG problem! You\'ve changed my code.';
      var doError = true;
      d = u;
      switch(d.toLowerCase())
      {
           case "_getdef":
               if(_getDef.toString().indexOf("z = s.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_getDef = "+_getDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_makedef":
               if(_makeDef.toString().indexOf("q = t.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_makeDef = "+_makeDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_define":
               if(_define.toString().indexOf("else if((h in j) ) {") != -1) { /*do nothing*/ }
               else { eval("_define = "+_define_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_access":
               if(_access.toString().indexOf("else { if(!f) { f = g; }") != -1) { /*do nothing*/ }
               else { eval("_access = "+_access_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           default:
                if(doError === true) { throw new Error('I don\'t know what to do.'); }
      }
  };

  /*Global function _doCodeCheck(String v). I named it doCodeCheck because we're 'doing a code check'. The argument
    'v' is the name of one of the first four functions in this script that you want to check. I make a different
    variable to make it harder for a user to figure out whats going on. You call this function in your code to check
    if any of the functions has been changed by the user.
  */
  self._doCodeCheck = function(v) {
      l = v;
      _doFunctionCheck(l);
  };
}())

看来安全性确实是一个问题,没有办法从客户端“隐藏”您的编程。对我来说,一个好主意是压缩您的代码,以使包括您,程序员在内的任何人都很难阅读和理解它。您可以找到一个网站:http : //javascriptcompressor.com/(这不是我的网站,请放心,我不是在做广告。)这个网站可以让您免费压缩和混淆Javascript代码。

  1. 复制以上脚本中的所有代码,然后将其粘贴到javascriptcompressor.com页面的顶部文本区域中。
  2. 选中“ Base62编码”复选框,选中“缩小变量”复选框。
  3. 按压缩按钮。
  4. 将所有内容粘贴并保存到.js文件中,然后将其添加到页面顶部的页面中。

显然,这表明需要标准化的跨浏览器const关键字。

但现在:

var myconst = value;

要么

Object['myconst'] = value;

两者似乎都足够,其他一切都像用火箭筒射击苍蝇。

在Greasemonkey脚本中使用const而不是var,但这是因为它们只能在Firefox上运行...

名称约定也确实是可行的方式(我俩都做!)。

在JavaScript中,我的实践是尽可能避免使用常量,而改用字符串。当您想将常量公开给外界时,会出现常量问题:

例如,可以实现以下Date API:

date.add(5, MyModule.Date.DAY).add(12, MyModule.Date.HOUR)

但是简单地写起来会更短,更自然:

date.add(5, "days").add(12, "hours")

这样,“天”和“小时”实际上就像常量,因为您无法从外部更改“小时”所代表的秒数。但是很容易覆盖MyModule.Date.HOUR

这种方法也将有助于调试。如果Firebug告诉您action === 18,很难理解其含义,但是当您看到时,action === "save"便会立即清楚。

好的,这很丑陋,但是它为我提供了Firefox和Chromium中的常量,Safari和Opera中的常量(WTF?),以及IE中的变量。

当然eval()是邪恶的,但是如果没有它,IE就会抛出错误,从而阻止脚本运行。

Safari和Opera支持const关键字,但是您可以更改const的value

在此示例中,服务器端代码将JavaScript写入页面,用值替换{0}。

try{
    // i can haz const?
    eval("const FOO='{0}';");
    // for reals?
    var original=FOO;
    try{
        FOO='?NO!';
    }catch(err1){
        // no err from Firefox/Chrome - fails silently
        alert('err1 '+err1);
    }
    alert('const '+FOO);
    if(FOO=='?NO!'){
        // changed in Sf/Op - set back to original value
        FOO=original;
    }
}catch(err2){
    // IE fail
    alert('err2 '+err2);
    // set var (no var keyword - Chrome/Firefox complain about redefining const)
    FOO='{0}';
    alert('var '+FOO);
}
alert('FOO '+FOO);

这有什么用?不多,因为它不是跨浏览器。充其量,也许至少有些浏览器不会让bookmarklet或第三方脚本修改该值,请稍稍放心

经过Firefox 2、3、3.6、4,Iron 8,Chrome 10、12,Opera 11,Safari 5,IE 6、9的测试。

如果值得一提的,你可以定义常量的角度使用$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');

Burke答案的改进版本,可让您CONFIG.MY_CONST代替CONFIG.get('MY_CONST')

它需要IE9 +或真实的Web浏览器。

var CONFIG = (function() {
    var constants = {
        'MY_CONST': 1,
        'ANOTHER_CONST': 2
    };

    var result = {};
    for (var n in constants)
        if (constants.hasOwnProperty(n))
            Object.defineProperty(result, n, { value: constants[n] });

    return result;
}());

*仅当初始值不可变时,这些属性才是只读的。

JavaScript ES6(重新)引入了所有主流浏览器都支持const关键字

通过声明的变量const无法重新声明或重新分配。

除此之外,其const行为类似于let

对于原始数据类型(布尔,空,未定义,数字,字符串,符号),它的行为符合预期:

const x = 1;
x = 2;
console.log(x); // 1 ...as expected, re-assigning fails

注意:请注意有关对象的陷阱:

const o = {x: 1};
o = {x: 2};
console.log(o); // {x: 1} ...as expected, re-assigning fails

o.x = 2;
console.log(o); // {x: 2} !!! const does not make objects immutable!

const a = [];
a = [1];
console.log(a); // 1 ...as expected, re-assigning fails

a.push(1);
console.log(a); // [1] !!! const does not make objects immutable

如果您确实需要一个不变且绝对恒定的对象:只需使用const ALL_CAPS即可使您的意图清楚。const无论如何都要遵循所有声明是一个好习惯,因此请仅依赖它。

另一种替代方法是:

var constants = {
      MY_CONSTANT : "myconstant",
      SOMETHING_ELSE : 123
    }
  , constantMap = new function ConstantMap() {};

for(var c in constants) {
  !function(cKey) {
    Object.defineProperty(constantMap, cKey, {
      enumerable : true,
      get : function(name) { return constants[cKey]; }
    })
  }(c);
}

然后简单地: var foo = constantMap.MY_CONSTANT

如果您这样做,constantMap.MY_CONSTANT = "bar"那将是无效的,因为我们正在尝试使用带有getter的赋值运算符,因此constantMap.MY_CONSTANT === "myconstant"将保持正确。

Javascript中已经存在常量您可以这样定义一个常量:

const name1 = value;

这不能通过重新分配而改变。

关键字“ const”是较早提出的,现在已正式包含在ES6中。通过使用const关键字,您可以传递将用作不可变字符串的值/字符串。

在JavaScript中引入常量充其量只是一种技巧。

在JavaScript中实现持久和可全局访问的值的一种好方法是声明一个带有一些“只读”属性的对象文字,如下所示:

            my={get constant1(){return "constant 1"},
                get constant2(){return "constant 2"},
                get constant3(){return "constant 3"},
                get constantN(){return "constant N"}
                }

您会将所有常量归为一个“我的”附件对象,您可以在其中查找存储的值或为此而决定放入其中的任何其他值。现在让我们测试一下是否可行:

           my.constant1; >> "constant 1" 
           my.constant1 = "new constant 1";
           my.constant1; >> "constant 1" 

如我们所见,“ my.constant1”属性保留了其原始值。您已经为自己设置了一些不错的“绿色”临时常量...

但是,当然,这只能防止您通过直接访问意外地修改,更改,无效或清空属性常量值,如给定示例所示。

否则我仍然认为常量是假的。我仍然认为,将自己的巨大自由换成一小部分欺骗性安全保障是最糟糕的交易。

Rhino.js工具const除了什么如上所述。

本文地址:http://javascript.askforanswer.com/javascriptzhongyouchangliangma.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!