1

I'm teaching an undergrad course in CS and I selected Javascript as a language because it is so light weight. I tried to write code and test it for the basis of all my lectures. Today I discovered that I had not correctly understood the output from my own code. I had fallen prey to the fault of thinking that because JavaScript is syntactically similar to a lot of other languages, it would handle scope like those languages. Apparently not. I have a couple of oddities and I hope someone will be able to explain. The whole of the code in question is below.

<html>
<script>
  function loadme()
  {
    contents.innerHTML="See this?";

    contents = 7;

    var tents = 7;
    other();
  }

  function other()
  {
    var otherTents = 7;
  }
</script>
<body onload="loadme()">
  <p id="contents"></p>
</body>
</html>

Question 1. Apparently the identifier contents in the first line of loadme refers to the p tag with that id. This seems to be consistent across browsers and suggests that there is an automatically generated set of variables which correspond to the ids of all HTML tags on the page. I didn't even know this was possible. And if not to make matters more confusing, I can overwrite the variable with any value because javascript is not strongly typed. Please if anyone has a reference to more fully explain this feature of the language, I would appreciate it.

Question 2. Although the variable tents isn't declared until the 5th line, if I examine the code at the first line it would appear to be in scope (even if the value is undefined). That's not particularly helpful. I originally considered that to mean the variable was not in scope. Now compare that with the otherTents variable which in Chrome is shown as "not available". Then tents is available? IE is less helpful in saying that tents=undefined while otherTents is undefined. Again, if anyone has a useful reference explaining what is going on with the Javascript scope, I would appreciate it.

Breakpoint analysis in two browsers

UPDATE UPDATE UPDATE UPDATE

There have been a lot of useful references on hoisting and I appreciate the pointer to the duplicate question on named elements. Very helpful. If I may follow up with a sub question to #2 does anyone have a comment on the non-standard handling of scope by the browsers. It seems that Chrome is at least distinguishing between out of scope and hoisted-but-undeclared. IE is less specific. Any thoughts?

BSD
  • 329
  • 3
  • 13
  • 3
    Question 1 isn't about a feature of the language, it's about a [non-standard feature of popular browsers](http://stackoverflow.com/q/6381425/5743988). Question 2 seems to be confusion about [hoisting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting). – 4castle Sep 14 '16 at 05:49
  • 1
    @4castle actually question 1 shows _standard_ behaviour. I agree it's stupid but it is actually explicitly covered in specs. It was first introduced in IE as non-standard then adopted as official. Most browsers do actually deviate from the spec in that they are supposed to do the same for name attributes, for example but they don't. Only IDs seem to be added to the window object. Even Edge does that as opposed to IE – VLAZ Sep 14 '16 at 06:09
  • maybe it's a good idea to introduce [`'use strict;'`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). this throws an error for use of undefined variables. – Nina Scholz Sep 14 '16 at 06:19
  • It's unusual how IE chose to show that `otherTents` was `undefined`, but both browsers seem to be trying to distinguish "undefined but in scope" from "undefined and not in scope". Both browsers are having the same behavior internally, it's just their debuggers are showing it in slightly different ways. – 4castle Sep 14 '16 at 20:45

1 Answers1

-1

Your first finding is new to me also so I will try to address your second question.

Variables can have two types of scope ie local or global.

All variables inside a function is considered a local variable. Unlike many other programming languages, JavaScript does not have a block level scoping. It only has function level scoping.

var appName = "Test";  // global variable

function test(name){   // name is a local variable
  var age = 20;        // age is a local variable

  console.log(weight); // undefined


  // Note that it does not throw an error saying "Uncaught ReferenceError: weight is not defined", 
  // This is because the variable is available but the value is not yet assigned. 
  // This is because of hoisting ie. all variables inside a function are hoisted (or lifted) to the top of the function


  var weight = 10;     // Over here the value gets assigned
}

Another incredible article on Hoisting

Graham
  • 7,431
  • 18
  • 59
  • 84
Flying Gambit
  • 1,238
  • 1
  • 15
  • 32
  • 1
    "Unlike many other programming languages, JavaScript does not have a block level scoping." — https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let – Quentin Sep 14 '16 at 06:45