避免在JavaScript中使用魔术数字 - 与JsHint一起使用的替代方案

时间:2012-08-21 08:52:41

标签: javascript magic-numbers

现在内置于PhpStorm的JSHint检查告诉了我关于JavaScript魔术数字的信息,并且我意识到它会制作更清晰的代码以避免使用它们。

我试过了:

var constants = {
    millisecs: 1000,
    secs: 60
};

还有这个:

var constants = function () {
    this.millisecs = 1000;
    this.getMillisecs = function () {
        return this.millisecs;
    };
};

JsHint抱怨两者。

this answer获取解决方案虽然可以正常工作:

var constants = (function() {
    var millisecs = 1000,
        defaultMsgsPerSecond = 60;
    this.getMillisecs = function() { return millisecs; };
    this.getDefaultMsgsPerSecond = function() { return defaultMsgsPerSecond; };
})();

大概是因为关闭。为什么这是被接受的,而从另一个SO问题中得到的另外两个建议不是?

编辑:虽然没有触发错误,但它实际上并不起作用。如果说常量未定义则错误。 JsFiddle

澄清 - 通过"工作"我的意思是"没有触发来自JsHint的警告"

2 个答案:

答案 0 :(得分:5)

在EcmaScript 6中,您可以做到:

const MILLISECS = 1000;
const DEFAULT_MSG_PER_SECOND = 60;

但在此之前,您可以使用EcmaScript 5的Object.freeze:

var constants = {
  millisecs: 1000,
  defaultMsgPerSecond: 60
};

var constants = Object.freeze(constants);

// Now constants is in fact... a constant!
constants.millisecs = 999;
constants.millisecs; // Still === 1000

如果你的本性是详细的,你可以试试Object.defineProperties:

var constants = {};

Object.defineProperties(constants, {
    'millisecs': {
        value: 1000,
        writable: false
     },
    'defaultMsgPerSecond': {
        value: 60,
        writable: false
     },
});

// Again, constants is in fact... a constant!
constants.millisecs = 999;
constants.millisecs; // Still === 1000

答案 1 :(得分:4)

关于您的修改

我想你想new内联对象:

var constants = new (function() {
    var millisecs = 1000,
        defaultMsgsPerSecond = 60;
    this.getMillisecs = function() { return millisecs; };
    this.getDefaultMsgsPerSecond = function() { return defaultMsgsPerSecond; };
})();

JSHint也会抱怨:Weird construction. Is 'new' unnecessary?

如果你将它用作闭包,那么你需要实际返回一些东西。如果不这样做,constants确实会包含undefined。一个简单的解决方法是返回this,但这将是一个糟糕的解决方案,因为您正在扩展this,这是您不拥有的对象的实例。

因此返回内联对象似乎是解决方案:

var constants = (function() {
    var millisecs = 1000,
        defaultMsgsPerSecond = 60;
    return {
        getMillisecs: function() { return millisecs; }
        getDefaultMsgsPerSecond: function() { return defaultMsgsPerSecond; }
    };
})();