0

Why does this code work?

function run(){
  var name =document.getElementById('name');
  name.classList.toggle('name');

}

But this code doesnt? var name is defined in the global scope so why isnt it accessible in the run function?

var name =document.getElementById('name');
function run(){    
  name.classList.toggle('name');
}
SLaks
  • 800,742
  • 167
  • 1,811
  • 1,896
  • It probably doesn't exist yet. – SLaks May 18 '18 at 16:41
  • Possible duplicate of [Why does jQuery or a DOM method such as getElementById not find the element?](https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – JJJ May 18 '18 at 16:42
  • `name` is also a native Global property of the `window` object and should always be avoided as an identifier name. – Scott Marcus May 18 '18 at 16:44
  • As for your main question, when is `run()` invoked and where is your code being placed within the HTML? – Scott Marcus May 18 '18 at 16:44

2 Answers2

1

run() isn't being called until after the DOM is fully parsed, so when it attempts to execute: document.getElementById('name');, the element will be found.

But, when that line is extracted from run() and placed outside of the function, it is being invoked prior to the DOM being fully parsed and the element is not found.

You can solve this by placing all of your code (or the script reference to your code), just before the closing body tag (</body>). By the time the browser encounters this, all of the HTML will have been parsed into memory and the element can be found.

.name { background: red; color: white;  }
<!doctype html>
<html>
<head>
</head>
<body>
  <div id="name" class="name" onclick="run()">Name</div>
  
  <!-- When the script is placed after all the other body content, it will
       be able to scan the DOM for any of that content. -->
  <script>
    var other =document.getElementById('name');
    function run(){
      other.classList.toggle('name');
    }
  </script>
</body>
</html>

And, as I mentioned in my comment, it's best not to ever name anything name because name is a property of the Global window object and complications can arise when you use that identifier.

Scott Marcus
  • 57,085
  • 6
  • 34
  • 54
-1

name is global property ie. window.name. Define the variable to something else:

    var other =document.getElementById('name');
    function run(){
      other.classList.toggle('name');
    }
.name {
  background: red;
  color: white;
  }
<div id="name" class="name" onclick="run()">Name</div>

It will work fine now.


Whilst, you use name, it will throw error:

var name =document.getElementById('name');
    function run(){
      name.classList.toggle('name');
    }
.name {
  background: red;
  color: white;
  }
<div id="name" class="name" onclick="run()">Name</div>

What's going on here?

You're modifying window property name with and html object. And you're using classList which is actually property of html object but not of window. So, accessing classList property on window property (though it's transformed to html object, it's still window object) will obviously throw you undefined error.

So, it's strongly discouraged to mutate the global property.


Inside the local scope, you're not modifying window property but defining local variable, so that works fine.

Bhojendra Rauniyar
  • 73,156
  • 29
  • 131
  • 187
  • 1
    *It will work fine now.* Not if the first line of code is executing before the DOM is loaded. `name` being a Global property is important (and why I mentioned it in my comment), but it's not necessarily the issue here. – Scott Marcus May 18 '18 at 16:47
  • 1
    Actually, you are misreading the question and taking something that I pointed out as a general FYI and proposed that as the problem/solution. – Scott Marcus May 18 '18 at 20:15