【问题标题】:How to check if a variable is undefined versus it is undeclared in javascript?如何检查变量是否未定义与在javascript中未声明?
【发布时间】:2021-01-31 23:48:51
【问题描述】:

我知道要查找 javascript 中是否未声明变量,我可以使用if (typeof variable === 'undefined')。如果我将变量声明为未定义 (var variable = undefined),则 if 语句仍然返回 true。是否有可能在 JavaScript 中找到未声明的变量和值为 undefined 的变量之间的区别?我知道它们是相似的,但是做const variable = undefined 然后variable = "something else" 会抛出一个错误,所以它们一定是不同的。

const variable = undefined

if (typeof variable === 'undefined') {
  console.log('"variable" is undefined')
}

if (typeof undeclaredVariable === 'undefined') {
  console.log('"undeclaredVariable" is undefined')
}

我不想使用 try catch 块,因为我希望能够基于此分配另一个常量。我想要这样的解决方案:const isVariableDeclared = variable === undeclared,除了 undeclared 在 javascript 中不存在。我知道我可以将 let 与 try catch 块一起使用,但我正在寻找更优雅的东西。

【问题讨论】:

  • 您的要求并不完全清楚。但是你在你的例子中调用undefinedVariable 更好地描述为未声明而不是未定义。从某种意义上说,你可以告诉这些,因为任何对它们的引用 except 用于 typeof 运算符都会抛出 ReferenceError
  • 使用“try catch”来引用变量。我认为这是检查变量是否已声明的唯一方法。
  • 没有,除了如果你使用一个除了赋值表达式或 typeof 运算符之外没有声明的变量,你的代码将不会运行,你会得到一个 ReferenceError。
  • 从您展示的示例中,您的意思是未声明吗?
  • 使用一个对象来定义它并检查对象内部是否有自己的属性,如果try catch不满足你,也许这是唯一的方法

标签: javascript undefined detection undeclared-identifier


【解决方案1】:

至少在撰写本文时...不,您似乎无法执行以下操作:

var a = undeclared(var) ? 'undeclared' : 'undefined'

原因是您不能将未声明的变量传递给函数;即使在非严格模式下也会引发错误。

我们能做的最好的是:

var barIsDeclared = true;

try { bar; }
catch (e) {
  if (e.name == "ReferenceError") {
    barIsDeclared = false;
  }
}

console.log(barIsDeclared);

为什么?

未定义:当变量已声明但未定义时发生 被赋予任何值。 undefined 不是关键字。

未声明:当我们尝试访问任何未声明的变量时会发生 之前使用 var 或 const 关键字初始化或声明。如果我们使用 'typeof' 运算符来获取未声明变量的值,我们将 面对运行时错误,返回值为“未定义”。范围 未声明的变量总是全局的。

例如:

  • 未定义:
var a;
undefined
console.log(a) // Success!
  • 未声明:
console.log(myVariable) // ReferenceError: myVariable is not defined

当我们尝试记录 undeclared 变量时,它会引发错误。尝试记录 undefined 变量不会。我们创建了一个try catch 来检查这一点。

'use strict'

值得一提的是,在您的代码中添加 'use strict' 可验证不存在未声明的变量,如果存在则引发错误。

function define() {
 //'use strict' verifies that no undeclared variable is present in our code     
 'use strict';     
 x = "Defined";  
}

define();

ReferenceError: x is not defined

延伸阅读:

【讨论】:

  • 很好的答案,虽然它不是一个理想的解决方案,但它帮助我想出了一个适合我的目的的解决方案。
【解决方案2】:

正如其他人已经指出的那样,OP 可能想要区分已声明但未定义的引用和未声明的引用名称...

let declaredButUnassignedAndStrictlyEqualToUndefinedValue;
const declaredAndHavingAssignedTheUndefinedValue = undefined;

// There is no way of telling the above two (un/)assignements appart.

console.log(
  '(declaredButUnassignedAndStrictlyEqualToUndefinedValue === declaredAndHavingAssignedTheUndefinedValue) ?',
  (declaredButUnassignedAndStrictlyEqualToUndefinedValue === declaredAndHavingAssignedTheUndefinedValue)
);


// the `typeof` operator is of no help
// if it comes to distinguish between
// declared but undefined references
// and undeclared reference names ...

console.log(
  'typeof notDeclaredWithinScope :', typeof notDeclaredWithinScope
);

// ... just a try catch can do that.

try {
  notDeclaredWithinScope;
} catch (err) {
  // console.log(err.message);

  console.log('`notDeclaredWithinScope` does not exist within this scope.')
}
.as-console-wrapper { min-height: 100%!important; top: 0; }

【讨论】:

  • 我正在寻找不同于 try catch 的另一种方法。不过答案很好,如果没有人有其他方法,我会接受。
  • @nthnchu ...只要按照原始 Q 的描述处理变量名,就几乎没有另一种方法。如果允许只关注属性名称和上下文,还有其他更优雅的解决方案。
【解决方案3】:

感谢大家的帮助!如果有人想要,我已经从所有答案中拼凑出一个简单的解决方案,可以满足我的需求。唯一的缺点是变量名必须作为字符串传递。它使用了一个 try catch 块,但我仍然可以将它用于我的原始用例(基于它分配一个常量)。

function declared(variable) {
  let declared = true;
  try {
    eval(variable);
  } catch (e) {
    if (e.name === "ReferenceError") {
      declared = false;
    }
  }
  return declared;
}

let declaredVar;
console.log(declared("declaredVar")); // true
console.log(declared("undeclaredVar")); // false


function typeOf(variable) {
  return eval("typeof " + variable) === "undefined"
    ? declared(variable)
      ? "undefined"
      : "undeclared"
    : eval("typeof " + variable);
}

const stringVar = "string";
const undefinedVar = undefined;
console.log(typeOf("stringVar")); // string
console.log(typeOf("undefinedVar")); // undefined
console.log(typeOf("undeclaredVar")); // undeclared

【讨论】:

    【解决方案4】:

    我明白你的意思。没有明确的方法可以获得确切的答案,但有一种方法可以确定它是否已定义。只有当它引用某处时才有可能。

    例如: // 假设 x 没有定义

    x.substring(1);

    输出: ReferenceError: "x" 未定义

    所以如果你使用 try catch 块方法,在 catch 错误信息的帮助下你可以识别它是否被定义!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 2018-09-09
      • 2019-05-11
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多