简体   繁体   中英

`var` comes as undefined but can't understand why

I have been trying to understand why my js code which was inside the HTML is not working now that it is in an external file. English is not my first language which makes me even harder to understand (and spanish results haven't been quite productive as I hoped).

I literally copy-paste the code to the other file and placed <script src="core.js"></script> to get the js loaded but both Firefox and Chrome keep telling me "TypeError: eng is undefined" when it is.

Before anyone tells me, it was already responded to in other questions, yes, I saw it was. But I don't understand anything so if anyone could explain me like "JS for dummies" would be REALLY appreciated.

The code is:

//SETS "LOCALE" "EN" TO REDIRECT TO ENGLISH
(function (){
  'use strict';

 var eng = document.querySelector('.eng')

  function setLocalStorage(){
     eng.addEventListener('click', () => {
      localStorage.setItem('locale','en')
    })
  }
  setLocalStorage()

}());

//SETS "LOCALE" "ES" TO REDIRECT TO SPANISH
(function (){
  'use strict';

  var esp = document.querySelector('.esp')

  function setLocalStorage(){
     esp.addEventListener('click', () => {
      localStorage.setItem('locale','es')
    })
  }
  setLocalStorage()

}());

//GETS THE "LOCALE" AND REDIRECT
(function () {
  'use strict';

  const locale = localStorage.getItem('locale');

  if (locale === 'en') {
    window.location = 'eng.html';

  } else if (locale === 'es') {
    window.location = 'esp.html';

  } else {
    // first visit:
    document
      .querySelector('.eng')
      .addEventListener('click', () => {
        localStorage.setItem('locale', 'en')
      });

    document
      .querySelector('.esp')
      .addEventListener('click', () => {
        localStorage.setItem('locale', 'es')
      });    
  }

}());

This line of JavaScript:

var eng = document.querySelector('.eng')

is trying to access an element on the HTML page, which probably looks like this:

<div class="eng">english text here</div>

In order for the JavaScript code to find that HTML element, the page must already be loaded before the JavaScript line of code runs. If not, the document.querySelector('.eng') expression will return null.

To improve the chances that the HTML will be loaded and available before the JavaScript runs, it is a good practice to put your scripts at the bottom of the <body> element. Something like this:

<body>
  <div class="eng">english text</div>
  <script src="myjavascript.js"></script>
<body>

But that's not a complete guarantee. To further improve your chances, you can add the defer attribute to the script tag, which prevents the script from running until after the page has loaded.

<script src="myjavascript.js" defer></script>

Issue #2 - Hoisting

There's a further problem with the JavaScript code that can cause an error. This has to do with "hoisting", where variables and function declarations are "hoisted" to the top of their blocks.

This JavaScript involves some hoisting:

function () {
  'use strict';

  var eng = document.querySelector('.eng');

  function setLocalStorage () {
    eng.addEventListener('click', () => {
      localStorage.setItem('locale', 'en');
    });
  }

  setLocalStorage();

}

Because of hoisting, it's actually doing this:

function () {

  // declare 'eng' as undefined
  var eng; 

  // declare setLocalStorage
  function setLocalStorage () {

    // JavaScript interpreter says during declaration:
    // "TypeError: I don't know what 'eng.addEventListener' is"

    eng.addEventListener('click', () => {
      localStorage.setItem('locale', 'en');
    });
  }

  // set 'eng'
  eng = document.querySelector('.eng');

  // now that 'eng' is set, call setLocalStorage
  setLocalStorage();

}

The fix - don't use an unset variable in a hoisted function. This code does the same thing, without any hoisting problems:

(function () {
  var eng = document.querySelector('.eng');

  eng.addEventListener('click', () => {
      localStorage.setItem('locale', 'en');
    });
})();

Actually according to your code you are accessing the DOM element and further you are calling them to do some task. But suppose you are trying to access some unavailable DOM content and then telling them to do something. In that case if you are trying to access some DOM but javascript couldn't find that it will return undefined . That's why you'll get undefined . (i'm trying to explain it easily)

Please make sure you have some elements with the class name eng and esp .

So, to overcome this case you need to check if you can access them and then give some task to do.

Suppose i'm checking here if eng is present there and then assigning some task to it.

eng && eng.addEventListener('click', () => {
    localStorage.setItem('locale','en')
})

Full Code is here.

//SETS "LOCALE" "EN" TO REDIRECT TO ENGLISH
(

    function (){
      'use strict';

     var eng = document.querySelector('.eng')

      function setLocalStorage(){
         eng && eng.addEventListener('click', () => {
          localStorage.setItem('locale','en')
        })
      }
      setLocalStorage()

    }());

    //SETS "LOCALE" "ES" TO REDIRECT TO SPANISH
    (function (){
      'use strict';

      var esp = document.querySelector('.esp')

      function setLocalStorage(){
         esp && esp.addEventListener('click', () => {
          localStorage.setItem('locale','es')
        })
      }
      setLocalStorage()

    }());

    //GETS THE "LOCALE" AND REDIRECT
    (function () {
      'use strict';

      const locale = localStorage.getItem('locale');

      if (locale === 'en') {
        window.location = 'eng.html';

      } else if (locale === 'es') {
        window.location = 'esp.html';

      } else {
        // first visit:
        document
          .querySelector('.eng')
          .addEventListener('click', () => {
            localStorage.setItem('locale', 'en')
          });

        document
          .querySelector('.esp')
          .addEventListener('click', () => {
            localStorage.setItem('locale', 'es')
          });    
      }

    }());

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