Question

I'm writing a static analyzer for JavaScript and I have to keep track of all of the local variables at any point of the code. What are all the ways to introduce new local variables to the scope in JavaScript?

Was it helpful?

Solution 2

Here are all the ones I have identified so far:

  • The standard library includes the following global variables: Array Boolean Date Function Number Object RegExp String Error EvalError RangeError ReferenceError SyntaxError TypeError URIError decodeURI decodeURIComponent encodeURI encodeURIComponent eval isFinite isNaN parseFloat parseIn Infinity JSON Math NaN undefined.
  • Variable declarations introduce a variable in the scope. e.g. var a, b, c, d=4.
    • Note that variable declarations are all lifted. e.g. function () { foob(x); var x = 12; } is functionally equivalent to function () { var x; foob(x); x = 12; }
  • Function statements and expressions. These not only bind the argument list but also create a local arguments variable.
    • Note that function statements are also lifted, e.g. function () { funcstatement(12); if (false) { function funcstatement(y) { y + 4; } } } is functionally equivalent to function () { function funcstatement(y) { y + 4; }; funcstatement(12); if (false) {}; }
  • Named function expressions introduce the name in the scope of the function, e.g. var x = function name() { /* 'name' available here */ }.
  • try {} catch (e) {} introduces the variable e only in the scope of the catch clause.

OTHER TIPS

Function expressions (and not function declaration statements) bind the (optional) function name to the environment inside the created function (but not outside). Here's a test:

function f1() {
  function f2(n) {
    if (n) {
      f2 = null;
      f2(0);
    }
    else
      console.log("f2");
  }
  f2(1);
  console.log(typeof f2);
}

f1();

That'll throw an error because overriding "f2" with null updates the value of the symbol "f2" in the outer ("f1") scope. Now, this variation:

function f1() {
  var f2 = function f2(n) {
    if (n) {
      f2 = null;
      f2(0);
    }
    else
      console.log("f2");
  }
  f2(1);
  console.log(typeof f2);
}

f1();

That works (logging first "f2" and then "function"). The assignment to "f2" throws no error but it doesn't do anything, because the name "f2" is bound as an immutable property of the scope. The assignment affects neither the inner "f2" nor the outer "f2".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top