在函数范围内声明的变量导致 if 语句出错
Variables declared inside the function scope causes if statement an error
所以我在 if 语句 var message
和 var 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 message
和 var body
都被提升到函数的顶部而没有被分配任何值(因此具有未定义的值)。
它只在 if 块中赋值,在 else 块中未定义。
"No var" 将查找范围链,直到它找到变量或命中全局范围(此时它将创建它)。当您从声明中删除 var 关键字时,var message
和 var body
被全局声明,并且还被分配了一个赋值中提供的值。因此它不会抛出错误。
在全局范围内声明这些变量而不给它们赋值会导致 var message
和 var body
在显式赋值之前未定义。因此 else 部分会抛出错误。
是的,关于变量是函数作用域而不是块作用域,你是正确的。但是,Javascript只会在到达赋值指令时才给你的变量赋值。在您的情况下,您将赋值指令 (message = document.createElement("p");
) 放入 if 中,这意味着当条件不满足时将不会执行该指令。并且 Javascript 被提升,这意味着 它将变量的所有声明(并且只有声明) 移动到函数的顶部。所以 message
的声明被移动到函数的顶部并保持 undefined
,当你试图访问 .parentNode
时你会得到错误,因为 undefined
没有属性。查看更多详细信息:https://scotch.io/tutorials/understanding-hoisting-in-javascript
所以我在 if 语句 var message
和 var 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 message
和 var body
都被提升到函数的顶部而没有被分配任何值(因此具有未定义的值)。
它只在 if 块中赋值,在 else 块中未定义。
"No var" 将查找范围链,直到它找到变量或命中全局范围(此时它将创建它)。当您从声明中删除 var 关键字时,var message
和 var body
被全局声明,并且还被分配了一个赋值中提供的值。因此它不会抛出错误。
在全局范围内声明这些变量而不给它们赋值会导致 var message
和 var body
在显式赋值之前未定义。因此 else 部分会抛出错误。
是的,关于变量是函数作用域而不是块作用域,你是正确的。但是,Javascript只会在到达赋值指令时才给你的变量赋值。在您的情况下,您将赋值指令 (message = document.createElement("p");
) 放入 if 中,这意味着当条件不满足时将不会执行该指令。并且 Javascript 被提升,这意味着 它将变量的所有声明(并且只有声明) 移动到函数的顶部。所以 message
的声明被移动到函数的顶部并保持 undefined
,当你试图访问 .parentNode
时你会得到错误,因为 undefined
没有属性。查看更多详细信息:https://scotch.io/tutorials/understanding-hoisting-in-javascript