简体   繁体   中英

Function won't work without a global variable?

I know this is probably a very novice question but I can't seem to find the answer online anywhere and I can't see why this is happening. So, at the risk of getting downvoted... I was hoping to find an answer here.

I almost have my code to work as I want it to, but I do not want to be using any global variables. However, whenever I put this variable into any of my function, the code stops working..

I would greatly appreciate some insight. Sorry if this question has been asked a thousand times. They way that I understand global/local binding - this shouldn't be happening?

Here is my code with comments out wherever I tried to place the variable instead of at the top of the function.

Thanks in advance.

<body>

    <div class="style" onclick="typeWriter()">
      <p id="remove">Hide Me</p>
      <p id="type"></p>
  </div>
</body>

//Javascript

  let letCounter = 0; //Do not want this as a global variable


  function hideInitText() {
    let hide = document.getElementById("remove");
    hide.classList.add("hide");
    //let letCounter = 0; //I tried here
  }
  hideInitText();

  function typeWriter() {
    //let letCounter = 0; //I tried here

    let cycle, classCounter; //establish the cycle and counter
    cycle = document.querySelectorAll("#type"); //cycle includes the .type class
    for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles
      //let letCounter = 0; //I tried here
      typeOut();
    }

    function typeOut() {
      //let letCounter = 0; //I tried here
      let speed = 50; //speed in milliseconds
      let typewriter = "Type me out"; //document.querySelectorAll(".type");
      if (letCounter < typewriter.length) {
        //let letCounter = 0; //I tried here
        //hide.classList.remove("hide"); //unhide the text
        cycle[classCounter].innerHTML += typewriter.charAt(letCounter);
        letCounter++;
        setTimeout(typeWriter, speed);
      }
    }
  };

One problem is

<div class="style" onclick="typeWriter()">

An inline handler will require either the referenced function to be global (or to be inside some with scopes, which should not be used). You'll need to attach the event listener with Javascript instead.

document.querySelector('div').addEventListener('click', typeWriter);

If you want letCounter to be scoped just to your script, you can put it (and everything else) inside an IIFE. That way, the scope of the letCounter is constrained to your module, and isn't global:

 (() => { let letCounter = 0; function hideInitText() { let hide = document.getElementById("remove"); hide.classList.add("hide"); } hideInitText(); function typeWriter() { let cycle, classCounter; //establish the cycle and counter cycle = document.querySelectorAll("#type"); //cycle includes the.type class for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles typeOut(); } function typeOut() { let speed = 50; //speed in milliseconds let typewriter = "Type me out"; //document.querySelectorAll(".type"); if (letCounter < typewriter.length) { //hide.classList.remove("hide"); //unhide the text cycle[classCounter].innerHTML += typewriter.charAt(letCounter); letCounter++; setTimeout(typeWriter, speed); } } } document.querySelector('div').addEventListener('click', typeWriter); })();
 <div class="style"> <p id="remove">Hide Me</p> <p id="type"></p> </div>

It looks like the letCounter variable is only being used inside the typeWriter function, so you could go further and scope letCounter to only inside that function. (It's usually a good idea to constrain variable scope as much as possible, after all)

 (() => { function hideInitText() { let hide = document.getElementById("remove"); hide.classList.add("hide"); } hideInitText(); const typeWriter = (() => { let letCounter = 0; return () => { let cycle, classCounter; //establish the cycle and counter cycle = document.querySelectorAll("#type"); //cycle includes the.type class for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles typeOut(); } function typeOut() { let speed = 50; //speed in milliseconds let typewriter = "Type me out"; //document.querySelectorAll(".type"); if (letCounter < typewriter.length) { //hide.classList.remove("hide"); //unhide the text cycle[classCounter].innerHTML += typewriter.charAt(letCounter); letCounter++; setTimeout(typeWriter, speed); } } }; })(); document.querySelector('div').addEventListener('click', typeWriter); })();
 <div class="style"> <p id="remove">Hide Me</p> <p id="type"></p> </div>

Functions need a global variable for the scenario you're doing where you want to increment the value each time.

The more complicated solution to this is change an attribute called “value” in your html and read it and set it each time treating it like a global variable.

You can add the letCounter into the DOM like this

 const element = document.getElementById('counter'); let letCounter = element.dataset.count;
 <div id="counter" data-count="0"></div>

I dislike the use of onclick="" method calls so i prefer the use of on eventListener.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM