当我认为它应该以未定义的方式响应时,我从一个阴影全局变量中获取了一个值。
我已经重写并压缩了原始代码,因为我不敢相信它应该有效,但它仍然有效。输入的 ID 为“num1”。 JS 写错了,要求“number1”的id。当代码加载时,num1 为空,但 show 函数中的 num1 从输入元素获取值,并显示在标签中,id 为输出。怎么会这样?我已经尝试过 chrome 和 edge 并得到了相同的结果。
"use strict";
const num1 = document.getElementById("number1");
const outp = document.getElementById("output");
function show() {
const num1 = parseFloat(globalThis.num1.value);
outp.innerHTML = num1;
}
<div>
<label for="num1">Number 1</label>
<input type="number" id="num1">
</div>
<button type="button" onclick="show()">Show</button>
<div>Output <label id="output"></label></div>
即使在 JavaScript 代码中错误定义了 num1 变量,代码仍然有效的原因是因为 JavaScript 的作用域工作方式。
在 JavaScript 中,用 const 关键字声明的变量是块作用域的,这意味着它们只存在于定义它们的块中。在这种情况下,第一个 num1 变量是在 show() 函数之外定义的,因此它在全局范围内。
但是,在 show() 函数内部,使用 const 关键字声明了一个新的 num1 变量。这个新变量“隐藏”了全局 num1 变量,有效地将它隐藏在函数之外。 show() 函数中的 num1 变量是一个完全不同的同名变量。
函数运行时,它会查找 globalThis.num1 值,该值是对 ID 为“num1”的实际输入元素的引用。这就是输入元素的值正确显示在输出标签中的原因,即使 JavaScript 中定义的 num1 变量不正确。
所以,尽管变量名称不匹配,但您从正确的输入元素获取值的原因是因为 globalThis.num1 指向 ID 为“num1”的正确输入元素,并且内部的 const num1 变量show() 函数仅用于存储输入元素值的解析值。
这是有效的,因为 HTML 代码中具有
id
属性集的元素会自动创建为全局 window
对象的属性(即:在您的情况下为 globalThis
)。这种行为有时被称为“命名元素”:
"use strict";
console.log(window.test); // `test` is a named element
console.log(test); // ends up accessing window.test
console.log(globalThis.test); // also same as accessing window.test
<input type="text" id="test" />
在上面,仅仅因为我们给我们的文本输入一个
id
的 "test"
,它现在在 window
上创建了一个我们可以访问的名为 test
的全局属性。虽然这可行,但被认为是最佳实践避免以这种方式访问元素,而是使用诸如.querySelector()
和.getElementById()
之类的方法
在你的情况下,你用
num1
声明你的
const
变量所以你的 num1
变量不会像你省略 window
或使用 globalThis
代替。因此,在 const
对象上自动添加的
var
属性保持原样,不会被您的变量声明覆盖。这意味着当您执行 num1
时,您不会访问您在周围范围内声明的变量,而是访问自动添加的 window 属性,当您为元素提供 id 时,您自然会获得该属性(例如上面的片段)。这就是为什么即使没有 window
声明,您的代码也能正常工作:
globalThis.num1
const num1
"use strict";
// const num1 = document.getElementById("number1");
const outp = document.getElementById("output");
function show() {
const num1 = parseFloat(globalThis.num1.value);
outp.innerHTML = num1;
}
<div>
<label for="num1">Number 1</label>
<input type="number" id="num1">
</div>
<button type="button" onclick="show()">Show</button>
<div>Output <label id="output"></label></div>
num1