JavaScript 中有常量吗?

发布于 2024-07-06 14:26:32 字数 82 浏览 6 评论 0原文

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

如果不是,指定用作常量的变量的常见做法是什么?

Is there a way to use constants in JavaScript?

If not, what's the common practice for specifying variables that are used as constants?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

心的位置 2024-07-13 14:26:32

ES2015 开始,JavaScript 就有了 const

const MY_CONSTANT = "some-value";

这将在 < a href="https://caniuse.com/#search=const" rel="noreferrer">几乎所有浏览器(IE 8、9 和 10 除外)。 有些可能还需要启用严格模式

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

var MY_CONSTANT = "some-value";

Since ES2015, JavaScript has a notion of const:

const MY_CONSTANT = "some-value";

This will work in pretty much all browsers except IE 8, 9 and 10. Some may also need strict mode enabled.

You can use var with conventions like ALL_CAPS to show that certain values should not be modified if you need to support older browsers or are working with legacy code:

var MY_CONSTANT = "some-value";
您的好友蓝忘机已上羡 2024-07-13 14:26:32

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

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() 方法:(。

如果您不需要严格保护变量值,那么只需按照建议进行操作并使用全部大写的约定。

Are you trying to protect the variables against modification? If so, then you can use a module pattern:

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

Using this approach, the values cannot be modified. But, you have to use the get() method on CONFIG :(.

If you don't need to strictly protect the variables value, then just do as suggested and use a convention of ALL CAPS.

薄情伤 2024-07-13 14:26:32

The const keyword is in the ECMAScript 6 draft but as of Aug 8, 2015 it had only enjoyed a smattering of browser support. For the current state, consider this ES6 compatibility table. The syntax is:

const CONSTANT_NAME = 0;
我不咬妳我踢妳 2024-07-13 14:26:32
"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。 如果您想使用常量引用,可以使用const也是只读的。

"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

See Object.freeze. You can use const if you want to make the constants reference read-only as well.

饭团 2024-07-13 14:26:32

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>

IE does support constants, sort of, e.g.:

<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>
如何视而不见 2024-07-13 14:26:32

ECMAScript 5 确实引入了 Object.defineProperty

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

所有现代浏览器都支持(以及 IE ≥ 9)。

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

ECMAScript 5 does introduce Object.defineProperty:

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

It's supported in every modern browser (as well as IE ≥ 9).

See also: Object.defineProperty in ES5?

平生欢 2024-07-13 14:26:32

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


@John 指出了常量的常见命名实践,该实践已在其他语言中使用多年,我认为你没有理由不能使用它。 当然,这并不意味着有人不会重写变量的值。 :)

No, not in general. Firefox implements const but I know IE doesn't.


@John points to a common naming practice for consts that has been used for years in other languages, I see no reason why you couldn't use that. Of course that doesn't mean someone will not write over the variable's value anyway. :)

乖乖 2024-07-13 14:26:32

在 JavaScript 中,我更喜欢使用函数返回常量值。

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


alert(MY_CONSTANT());

In JavaScript, my preference is to use functions to return constant values.

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


alert(MY_CONSTANT());
贪了杯 2024-07-13 14:26:32

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 等)。 所以 varfunction(){return} 没有区别。 const 是唯一的实常量。

更新:
IE11 支持 const

IE11 支持新兴 ECMAScript 6 标准中定义明确且常用的功能,包括 let、constMap、< code>Set 和 WeakMap 以及 __proto__ 以提高互操作性。

Mozillas MDN Web Docs contain good examples and explanations about const. Excerpt:

// 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;

But it is sad that IE9/10 still does not support const. And the reason it's absurd:

So, what is IE9 doing with const? So
far, our decision has been to not
support it. It isn’t yet a consensus
feature as it has never been available
on all browsers.

...

In the end, it seems like the best
long term solution for the web is to
leave it out and to wait for
standardization processes to run their
course.

They don't implement it because other browsers didn't implement it correctly?! Too afraid of making it better? Standards definitions or not, a constant is a constant: set once, never changed.

And to all the ideas: Every function can be overwritten (XSS etc.). So there is no difference in var or function(){return}. const is the only real constant.

Update:
IE11 supports const:

IE11 includes support for the well-defined and commonly used features of the emerging ECMAScript 6 standard including let, const, Map, Set, and WeakMap, as well as __proto__ for improved interoperability.

折戟 2024-07-13 14:26:32

如果您不介意使用函数:

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

这种方法为您提供函数而不是常规变量,但它保证*一旦设置值,任何人都无法更改它。

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

我个人觉得这相当令人愉快,特别是在习惯了淘汰赛可观察到的这种模式之后。

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

If you don't mind using functions:

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

This approach gives you functions instead of regular variables, but it guarantees* that no one can alter the value once it's set.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

I personally find this rather pleasant, specially after having gotten used to this pattern from knockout observables.

*Unless someone redefined the function constant before you called it

弥繁 2024-07-13 14:26:32

使用“新”对象 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

注意:赋值将在控制台中返回给您分配的值,但是变量的值不会改变

with the "new" Object api you can do something like this:

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

take a look at this on the Mozilla MDN for more specifics. It's not a first level variable, as it is attached to an object, but if you have a scope, anything, you can attach it to that. this should work as well.
So for example doing this in the global scope will declare a pseudo constant value on the window (which is a really bad idea, you shouldn't declare global vars carelessly)

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

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

note: assignment will give you back the assigned value in the console, but the variable's value will not change

独木成林 2024-07-13 14:26:32

忘记 IE 并使用 const 关键字。

Forget IE and use the const keyword.

笑看君怀她人 2024-07-13 14:26:32

尽可能将常量分组到结构中:

例如,在我当前的游戏项目中,我使用了以下内容:

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。

Group constants into structures where possible:

Example, in my current game project, I have used below:

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

Assignment:

var wildType = CONST_WILD_TYPES.REGULAR;

Comparision:

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

More recently I am using, for comparision:

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

IE11 is with new ES6 standard that has 'const' declaration.
Above works in earlier browsers like IE8, IE9 & IE10.

失去的东西太少 2024-07-13 14:26:32

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

/* 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  

You can easily equip your script with a mechanism for constants that can be set but not altered. An attempt to alter them will generate an error.

/* 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  
樱&纷飞 2024-07-13 14:26:32

然而,没有确切的跨浏览器预​​定义方法来做到这一点,您可以通过控制变量的范围来实现它,如其他答案所示。

但我建议使用名称空间来区别于其他变量。 这会将其他变量发生碰撞的可能性降到最低。

使用它时,正确的命名空间

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 进行冻结方法。


如果您可以调用函数,那么以下是定义常量的最佳跨浏览器方法。 在自执行函数中确定对象的作用域并为常量返回 get 函数
ex:

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')


** 在这两个示例中,您必须非常小心名称间距,以便您的对象或函数不应该通过其他库替换。(如果对象或函数本身将被替换,您的整个常量将消失)

Yet there is no exact cross browser predefined way to do it , you can achieve it by controlling the scope of variables as showed on other answers.

But i will suggest to use name space to distinguish from other variables. this will reduce the chance of collision to minimum from other variables.

Proper namespacing like

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

so while using it will be iw_constant.name or iw_constant.age

You can also block adding any new key or changing any key inside iw_constant using Object.freeze method. However its not supported on legacy browser.

ex:

Object.freeze(iw_constant);

For older browser you can use polyfill for freeze method.


If you are ok with calling function following is best cross browser way to define constant. Scoping your object within a self executing function and returning a get function for your constants
ex:

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

       };

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

//to get the value use
iw_constant('name') or iw_constant('age')


** In both example you have to be very careful on name spacing so that your object or function shouldn't be replaced through other library.(If object or function itself wil be replaced your whole constant will go)

鸩远一方 2024-07-13 14:26:32

有一段时间,我在传递给 with() 语句的对象文字中指定了“常量”(实际上仍然不是常量)。 我觉得这真是太聪明了。 这是一个示例:

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

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

现在,我只需执行 var MY_CONST = 'whatever'; 即可 KISS

For a while, I specified "constants" (which still weren't actually constants) in object literals passed through to with() statements. I thought it was so clever. Here's an example:

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

In the past, I also have created a CONST namespace where I would put all of my constants. Again, with the overhead. Sheesh.

Now, I just do var MY_CONST = 'whatever'; to 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;

My opinion (works only with objects).

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

Try! But understand - this is object, but not simple variable.

Try also just:

const a = 9;
驱逐舰岛风号 2024-07-13 14:26:32

我也遇到过这个问题。 经过很长一段时间寻找答案并查看每个人的所有回应后,我想我已经找到了一个可行的解决方案。

看来我遇到的大多数答案都是使用函数来保存常量。 正如许多论坛的许多用户所发表的那样,客户端的用户可以轻松地重写这些函数。 我对 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 文件中,然后将其添加到页面的头部。

I too have had a problem with this. And after quite a while searching for the answer and looking at all the responses by everybody, I think I've come up with a viable solution to this.

It seems that most of the answers that I've come across is using functions to hold the constants. As many of the users of the MANY forums post about, the functions can be easily over written by users on the client side. I was intrigued by Keith Evetts' answer that the constants object can not be accessed by the outside, but only from the functions on the inside.

So I came up with this solution:

Put everything inside an anonymous function so that way, the variables, objects, etc. cannot be changed by the client side. Also hide the 'real' functions by having other functions call the 'real' functions from the inside. I also thought of using functions to check if a function has been changed by a user on the client side. If the functions have been changed, change them back using variables that are 'protected' on the inside and cannot be changed.

/*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);
  };
}())

It also seems that security is really a problem and there is not way to 'hide' you programming from the client side. A good idea for me is to compress your code so that it is really hard for anyone, including you, the programmer, to read and understand it. There is a site you can go to: http://javascriptcompressor.com/. (This is not my site, don't worry I'm not advertising.) This is a site that will let you compress and obfuscate Javascript code for free.

  1. Copy all the code in the above script and paste it into the top textarea on the javascriptcompressor.com page.
  2. Check the Base62 encode checkbox, check the Shrink Variables checkbox.
  3. Press the Compress button.
  4. Paste and save it all in a .js file and add it to your page in the head of your page.
情归归情 2024-07-13 14:26:32

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

但就目前而言:

var myconst = value;

或者

Object['myconst'] = value;

两者似乎都足够了,其他任何事情都就像用火箭筒射苍蝇一样。

Clearly this shows the need for a standardized cross-browser const keyword.

But for now:

var myconst = value;

or

Object['myconst'] = value;

Both seem sufficient and anything else is like shooting a fly with a bazooka.

你曾走过我的故事 2024-07-13 14:26:32

我在 Greasemonkey 脚本中使用 const 而不是 var,但这是因为它们只能在 Firefox 上运行...
名称约定确实也是一种可行的方法(我两者都做!)。

I use const instead of var in my Greasemonkey scripts, but it is because they will run only on Firefox...
Name convention can be indeed the way to go, too (I do both!).

同尘 2024-07-13 14:26:32

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

例如,可以实现以下日期 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" 时,它就立即清楚了。

In JavaScript my practice has been to avoid constants as much as I can and use strings instead. Problems with constants appear when you want to expose your constants to the outside world:

For example one could implement the following Date API:

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

But it's much shorter and more natural to simply write:

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

This way "days" and "hours" really act like constants, because you can't change from the outside how many seconds "hours" represents. But it's easy to overwrite MyModule.Date.HOUR.

This kind of approach will also aid in debugging. If Firebug tells you action === 18 it's pretty hard to figure out what it means, but when you see action === "save" then it's immediately clear.

遥远的她 2024-07-13 14:26:32

好吧,这很难看,但它在 Firefox 和 Chromium 中给了我一个常量,在 Safari 和 Opera 中给了一个不恒定的常量(WTF?),在 IE 中给了一个变量。

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

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

在此示例中,服务器端代码将 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);

这有什么用? 不多,因为它不是跨浏览器的。 充其量,也许可以让您安心一点,至少某些浏览器不会让书签或第三方脚本修改该值。

使用 Firefox 2、3、3.6、4、Iron 8、Chrome 10、12、Opera 11、Safari 5、IE 6、9 进行测试。

Okay, this is ugly, but it gives me a constant in Firefox and Chromium, an inconstant constant (WTF?) in Safari and Opera, and a variable in IE.

Of course eval() is evil, but without it, IE throws an error, preventing scripts from running.

Safari and Opera support the const keyword, but you can change the const's value.

In this example, server-side code is writing JavaScript to the page, replacing {0} with a value.

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);

What is this good for? Not much, since it's not cross-browser. At best, maybe a little peace of mind that at least some browsers won't let bookmarklets or third-party script modify the value.

Tested with Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.

少女情怀诗 2024-07-13 14:26:32

如果值得一提,您可以使用 Angular 定义常量。 org/api/auto/service/$provide#constant" rel="nofollow">$provide.constant()

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

If it is worth mentioning, you can define constants in angular using $provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');
一口甜 2024-07-13 14:26:32

Burke 的答案的改进版本,可让您执行 CONFIG.MY_CONST 而不是 CONFIG .get('MY_CONST')

它需要 IE9+ 或真正的网络浏览器。

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;
}());

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

An improved version of Burke's answer that lets you do CONFIG.MY_CONST instead of CONFIG.get('MY_CONST').

It requires IE9+ or a real web browser.

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;
}());

* The properties are read-only, only if the initial values are immutable.

悲喜皆因你 2024-07-13 14:26:32

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

通过 const 声明的变量不能重新声明或重新赋值。

除此之外,const 的行为类似于

它的行为与原始数据类型(布尔、空、未定义、数字、字符串、符号)的预期相同:

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 声明来说,这是一个很好的约定,因此只需依赖它即可。

JavaScript ES6 (re-)introduced the const keyword which is supported in all major browsers.

Variables declared via const cannot be re-declared or re-assigned.

Apart from that, const behaves similar to let.

It behaves as expected for primitive datatypes (Boolean, Null, Undefined, Number, String, Symbol):

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

Attention: Be aware of the pitfalls regarding objects:

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

If you really need an immutable and absolutely constant object: Just use const ALL_CAPS to make your intention clear. It is a good convention to follow for all const declarations anyway, so just rely on it.

╰つ倒转 2024-07-13 14:26:32

另一种选择是这样的:

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" 将保持 true。

Another alternative is something like:

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);
}

Then simply: var foo = constantMap.MY_CONSTANT

If you were to constantMap.MY_CONSTANT = "bar" it would have no effect as we're trying to use an assignment operator with a getter, hence constantMap.MY_CONSTANT === "myconstant" would remain true.

老旧海报 2024-07-13 14:26:32

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

const name1 = value;

这不能通过重新分配来更改。

in Javascript already exists constants. You define a constant like this:

const name1 = value;

This cannot change through reassignment.

梦冥 2024-07-13 14:26:32

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

The keyword 'const' was proposed earlier and now it has been officially included in ES6. By using the const keyword, you can pass a value/string that will act as an immutable string.

忘东忘西忘不掉你 2024-07-13 14:26:32

将常量引入 JavaScript 充其量只是一种 hack。

在 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”属性保留了其原始值。 您已经为自己创建了一些漂亮的“绿色”临时常量...

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

否则我仍然认为常量是给傻瓜用的。
我仍然认为,用你的巨大自由来换取一小部分欺骗性的安全是最糟糕的交易。

Introducing constants into JavaScript is at best a hack.

A nice way of making persistent and globally accessible values in JavaScript would be declaring an object literal with some "read-only" properties like this:

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

you'll have all your constants grouped in one single "my" accessory object where you can look for your stored values or anything else you may have decided to put there for that matter. Now let's test if it works:

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

As we can see, the "my.constant1" property has preserved its original value. You've made yourself some nice 'green' temporary constants...

But of course this will only guard you from accidentally modifying, altering, nullifying, or emptying your property constant value with a direct access as in the given example.

Otherwise I still think that constants are for dummies.
And I still think that exchanging your great freedom for a small corner of deceptive security is the worst trade possible.

北斗星光 2024-07-13 14:26:32

除了上面提到的之外,Rhino.js 还实现了 const

Rhino.js implements const in addition to what was mentioned above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文