如何检查ES6“变量”是否恒定?

时间:2015-04-04 18:35:16

标签: javascript ecmascript-6

有谁知道一些技巧怎么做?我尝试使用try-catch

"use strict";

const a = 20;

var isConst = false;
try {
   var temp = a; a = a+1; a = temp;
} catch (e) {
   isConst = true;
}

但不幸的是,它仅适用于" strict"模式。没有"使用严格"它以静默方式执行所有语句,而不修改a。此外,我无法将此代码包装到一些方便的函数中(例如isConstant(someConst)),因为我传递给该函数的任何参数都将是一个新变量。所以任何人都知道如何创建isConstant()函数?

4 个答案:

答案 0 :(得分:2)

我认为没有,但我也不认为这是一个大问题。我认为有能力知道变量是否为const并且存在于其他一些语言中可能是有用的,但实际上,因为您(或团队中的某个人)将定义这些变量,您和# 39; d知道变量的范围和类型。换句话说,不,你不能,但它也不是问题。

唯一可能有用的情况是,如果您可以在运行时更改mutable属性,并且更改此属性具有实际的性能优势; letconstvar与编译器大致相同,唯一的区别是编译器会跟踪const并在编译之前检查分配。

另外需要注意的是,就像let一样,const的范围限定为当前范围,所以如果您有类似的内容:

'use strict';

const a = 12;

// another scope
{
  const a = 13;
}

它有效。请注意,如果您未在新范围内明确说明const a = 13,它会在更高的范围内查找,并且会出现Read OnlyAssignment错误:

'use strict';

const a = 12;

{
  a = 13; // will result in error
}

答案 1 :(得分:1)

基于此处的一些答案,我编写了此代码段(用于客户端JS),该代码段将告诉您最后一次声明“变量”的方式-我希望它很有用。

使用以下命令找出x的最后声明(取消注释x的声明以对其进行测试):

// x = 0
// var x = 0
// let x = 0
// const x = 0

const varName = "x"    
console.log(`Declaration of ${varName} was...`)
try {
  eval(`${varName}`)
  try {
    eval(`var ${varName}`);
    console.log("... last made with var")
  } catch (error) {
    try {
      eval(`${varName} = 0`)
      console.log("... last made with let")
    } catch (error) {
      console.log("... last made with const")
    }
  }
} catch (error) {
  console.log("... not found. Undeclared.")
}

有趣的是,在没有varletconstx = 0的情况下进行声明会导致var默认使用。同样,使用var在函数范围中重新声明函数参数。

答案 2 :(得分:0)

只需检查您的重新分配是否真的有所作为:

var isConst = function(name, context) {
  // does this thing even exist in context?
  context = context || this;
  if(typeof context[name] === "undefined") return false;
  // if it does exist, a reassignment should fail, either
  // because of a throw, or because reassignment does nothing.
  try {
    var _a = context[name];
    context[name] = !context[name];
    if (context[name] === _a) return true;
    // make sure to restore after testing!
    context[name] = _a;
  } catch(e) { return true; }
  return false;
}.bind(this);

你需要try / catch因为重新分配可以抛出异常(比如在Firefox中),但是当它没有(比如在Chrome中)时,你只需检查你的“这总是会改变价值“重新分配实际做了任何事情。

一个简单的测试:

const a = 4;
var b = "lol";
isConst('a'); // -> true
isConst('b'); // -> false

如果您在不同的上下文中声明了consts,则传递该上下文以强制解析正确的对象。

缺点:这不适用于在对象范围之外声明的变量。好处:在其他地方宣布它们是完全没有意义的。例如,在函数范围内声明它们会导致const关键字无用:

function add(a) {
  return ++a;
}

function test() {
  const a = 4;
  console.log(add(a));
}

test(); // -> 5

即使a在test()中是常量,如果你将它传递给其他任何东西,它也会作为常规的可变值传递,因为它现在只是arguments列表中的“一件事”。 / p>

此外,拥有const的唯一原因是因为它没有改变。因此,不断重新创建它,因为你正在调用一个不止一次使用它的函数,这意味着你的const应该在函数之外生存,所以再一次,我们被迫将变量放在一个对象中范围。

答案 3 :(得分:-1)

该问题涉及早期ES6实施中的不合规行为,尤其是V8(Node.js 4和传统Chrome版本)。现代ES6实现中不存在这个问题,无论是在严格模式还是在草率模式下。 const重新分配应始终生成TypeError,可以使用try..catch进行重新分配。

无法isConstant函数,因为const变量的值无法识别。

最好在严格模式下运行脚本,从而避免特定于草率模式的问题。

即使在草率模式中定义了变量,也可以在嵌套函数范围中启用严格模式:

const foo = 1;
// ...
let isConst = false;

(() => {
  'use strict';

  try {
    const oldValue = foo;
    foo = 'new value';
    foo = oldValue;
  } catch (err) {
     isConst = true;
  }
})();

使用JavaScript和其他语言中使用的UPPERCASE_CONSTANT约定是有益的。它允许在没有IDE帮助的情况下明确地将变量识别为常量,并避免大多数意外重新分配的问题。