在函数范围内声明的变量导致 if 语句出错

Variables declared inside the function scope causes if statement an error

所以我在 if 语句 var messagevar body 的回调函数中声明了两个变量,现在当我 运行 代码时,当 if 语句命中 else 语句然后抛出 Uncaught TypeError: Cannot read property 'parentNode' of undefined at HTMLButtonElement.<anonymous> 当我从声明中删除 var 关键字并全局声明它们时,我没有收到任何错误。问题是什么?我认为 javascript 是函数作用域语言,而不是块作用域。即使在函数顶部的 if 语句之外声明它们变量也无济于事。

代码:

function clickBtn() {
  var btn = document.getElementById("button");
  btn.addEventListener("click", function () {
    if (theName.value == "") {
      var message = document.createElement("p");
      message.className = "message";
      message.innerHTML = "You forgot the name and email";
      var body = document.getElementsByTagName("body")[0];
      body.appendChild(message);
    } else {

    message.parentNode.removeChild(message);
    var user1 = new User (theName.value, theEmail.value);
    users.push(user1);
    console.log(JSON.stringify(users, null, 2));
  }
    theName.value = "";
    theEmail.value = "";
  });
}
clickBtn();

if 的值是 true 时,你只给 message 赋值。

else 分支只有一个未定义的值 message,这就是您收到此错误的原因。

您可以通过声明 message 变量具有 if/else 语句之外的值来解决此问题。


您似乎想要 添加 if 中的消息并 删除 else 中的消息- 为此,您需要能够获得 相同的消息 。您所做的是每次创建 一条新消息

这是您可以执行的操作的示例(基于您的代码):

function clickBtn() {
  var btn = document.getElementById("button");
  btn.addEventListener("click", function () {
    if (theName.value == "") {
      var message = document.createElement("p");
      message.className = "message";
      message.innerHTML = "You forgot the name and email";
      var body = document.getElementsByTagName("body")[0];
      body.appendChild(message);
    } else {
      message = document.getElementsByClassName("message")[0]; // first one
      message.parentNode.removeChild(message);
      var user1 = new User (theName.value, theEmail.value);
      users.push(user1);
      console.log(JSON.stringify(users, null, 2));
  }
    theName.value = "";
    theEmail.value = "";
  });
}
clickBtn();

如果 if 语句为真,则声明变量,如果为假,则引用它。在 if 语句之前声明 var message=... 它应该可以工作。

I tho javascript is function scope language, not block scope

现代代码看起来有点不同,其目标是函数式风格和不变性。随着版本 6 的 ES-262 也更高,希望只使用 const 和 let,并且为了将来与 ES 模块的兼容性直接包括使用严格模式。 在将此类更正输入代码后,阶段运行时的错误很可能会传递到阶段的编译时。此外,如果需要,最好解决功能关闭问题,而不是使用全局信息字段。

Javascript有个变量的概念hoisting。 Javascript 确实是函数范围语言,而不是块范围语言。 在您的情况下, var messagevar body 都被提升到函数的顶部而没有被分配任何值(因此具有未定义的值)。

它只在 if 块中赋值,在 else 块中未定义。

"No var" 将查找范围链,直到它找到变量或命中全局范围(此时它将创建它)。当您从声明中删除 var 关键字时,var messagevar body 被全局声明,并且还被分配了一个赋值中提供的值。因此它不会抛出错误。

在全局范围内声明这些变量而不给它们赋值会导致 var messagevar body 在显式赋值之前未定义。因此 else 部分会抛出错误。

是的,关于变量是函数作用域而不是块作用域,你是正确的。但是,Javascript只会在到达赋值指令时才给你的变量赋值。在您的情况下,您将赋值指令 (message = document.createElement("p");) 放入 if 中,这意味着当条件不满足时将不会执行该指令。并且 Javascript 被提升,这意味着 它将变量的所有声明(并且只有声明) 移动到函数的顶部。所以 message 的声明被移动到函数的顶部并保持 undefined,当你试图访问 .parentNode 时你会得到错误,因为 undefined 没有属性。查看更多详细信息:https://scotch.io/tutorials/understanding-hoisting-in-javascript