【问题标题】:Scope error in JavaScriptJavaScript 中的范围错误
【发布时间】:2018-07-07 19:18:00
【问题描述】:

我正在用 javascript 在 html 中使用 input[range]。我想出了一个问题。这是代码:-

<html>
<head>
<meta charset="utf-8">
<title>Slider and range !!</title>
<script type="text/javascript">
let div = document.getElementById('display');
  function foo(value) {

    div.innerHTML = value;
  }
</script>
<style>
input[type='range']{
  border : 5px grey solid;
  border-radius: 10px;
}
</style>
</head>
<body>
  <input id="input" type="range" min = '0' max ='100' step="10" oninput="foo(this.value)" >
  <div id="display"></div>
</body>
</html>

在 webconsole 中 div 显示为未定义,但如果我将函数声明为:-

  function foo(value) {
    let div = document.getElementById('display');
    div.innerHTML = value;
  }

代码正在运行。为什么会这样?请帮助
谢谢。

【问题讨论】:

  • 因为您尝试在加载 div 之前获取它。将整个内容封装在 window.onload 监听器中。
  • 试着把你的脚本放在页面底部
  • @Jonas W. 它不工作

标签: javascript html dom html-parsing


【解决方案1】:

让我们了解 DOM 解析是如何在 Browser 上工作的。

当我们在 DOM/Browser 上加载任何文档/HTML 时,它会开始文档解析。它迭代元素并创建一个 DOM 树。它从 TOP 开始,到 header 并检查其他资源并一一执行。

这里是你写的时候

 let div = document.getElementById('display');

在没有将其包装到任何函数中的简单脚本标记中,它首先执行而没有加载您的 DOM。

这意味着,解析器正在通过浏览器上尚不存在的 ID 查找 DIV。因此它是未定义的。现在的问题是它在函数内部是如何工作的?

JavaScript 中的函数在 DOMContentLoaded 上执行。这类似于jQuery ready()。这确保了 DOM 已经准备好并且浏览器上的每个元素都已经被遍历并且现在位于 DOM 树中。

现在,您可能在想我们将这段代码放在页面底部时它是如何工作的?喜欢

<html>
  <head></head>
  <body>
     YOUR HTML 
  </body>
  <script type="text/javascript">
      //YOUR JS CODE
  </script>

因此,当我们插入 JS 时,它正在页面顶部的 head 标记中查找 DOM 中的元素,并且如果在执行 JS 时出现错误(就像在您的情况下,JS 正在寻找 DIV 而不是在 DOM 上)除非脚本解决了错误,否则它将停止 DOM 的执行。

因此,当我们将 JS 代码放在页面底部时,浏览器已经解析了所有页面元素,并且 DOM 树已准备就绪。因此,任何元素现在都可以被 JS 访问。

这意味着,如果您在页面底部编写上述代码,它将正确获取元素。

脚注:

阅读更多关于 JavaScript 如何在浏览器上工作的信息 https://javascript.info/onload-ondomcontentloaded

Where should I put <script> tags in HTML markup?

希望这会有所帮助,

谢谢 -AG

【讨论】:

    【解决方案2】:

    第一种方法不起作用,因为您尝试访问尚未加载的 DOM 元素。 let div = document.getElementById('display'); 通过此代码您尝试立即访问。当 JS 代码在全局范围内时,它会逐行解析,并且所有行都会立即执行。

    但是下面的代码工作正常,因为在这里您访问函数范围内的 DOM 元素,并且函数仅在 range 值发生变化时运行,同时 DOM 已经加载并可供操作。

    function foo(value) {
        let div = document.getElementById('display'); // Now `display` available, so no error
        div.innerHTML = value;
    }
    

    【讨论】:

      【解决方案3】:

      您尝试在加载之前访问display 元素。您必须将脚本放在 HTML 文件的较低位置,或者使其在文档的 onLoad 函数处执行。

      document.onload = function() {
      
          //run your code here
      }
      

      【讨论】:

      • div 在全局范围内定义。在全局范围内与 let 或 var 有什么区别吗?
      • 你是对的。唯一的区别是let 在全局范围内定义时不会添加为window 对象的属性。答案已编辑。
      【解决方案4】:

      检查这个,在页面底部给出脚本,

      表示初始化div变量,只有在渲染页面之后

      <html>
      
      <head>
        <meta charset="utf-8">
        <title>Slider and range !!</title>
        <script type="text/javascript">
          let div;
      
          function onLoadFunction() {
            div = document.getElementById('display');
          }
      
          function foo(value) {
            div.innerHTML = value;
          }
        </script>
        <style>
          input[type='range'] {
            border: 5px grey solid;
            border-radius: 10px;
          }
        </style>
      </head>
      
      <body onLoad="onLoadFunction()">
        <input id="input" type="range" min='0' max='100' step="10" oninput="foo(this.value)">
        <div id="display"></div>
      </body>
      
      
      </html>

      【讨论】:

      • 如果给我添加 onload 事件在正文中的函数,并在该函数中我分配 div 变量,div 被声明为全局......它会工作吗?跨度>
      • 是的,它会起作用,但您必须确保全局分配值,意味着没有let关键字,或者在外部声明变量并在onload函数内部初始化它
      • @UzumakiSaptarshi 我已经更新了我的代码,就像我上面的声明一样,检查一下,
      猜你喜欢
      • 2013-12-04
      • 1970-01-01
      • 2018-07-06
      • 1970-01-01
      • 2014-03-16
      • 2011-04-16
      • 2023-04-07
      • 2023-02-26
      • 2017-04-02
      相关资源
      最近更新 更多