-1

I'm working on a project developed by someone else. I load the Chrome Developer Tool to check the status of a global variable. When I tick open Global under Scope, I see a colossal number of global variables. It takes me over 8 seconds to scroll through them. Having worked on this project for some time now, I know that global variables is a problem which we'll have to fix; but, *that is irrelevant to my question.

To communicate the scale of our global scope being flooded, I'd like to count the number of variables presently instantiated in the global scope

How do I do this?

I'm looking for an answer in JavaScript that I can execute immediately in my console. Basically something that may iterate over the global scope and count++.

KareemElashmawy
  • 251
  • 5
  • 16
  • 1
    Iterate through `window`'s properties? Beware of prototypal members if you don't want to count those. – Andrew Li Jun 07 '17 at 00:34
  • Chances are, this codebase has a lot of other problems. There are static code analysis tools that may be of more use to you. I've used Code Climate before. It picks up on a lot of things. Just be careful with these tools... the reports they generate are meant to be a guide, not a definitive TODO list. There will always be things it picks up on that are fine, and it will likely miss some things as well. But if you just want a how-screwed-am-i metric, those tools are pretty good. – Brad Jun 07 '17 at 00:34
  • @AndrewLi That's what I was thinking; but, I've never worked with JS to iterate through global or window properties. (I try to work exclusively with objects or simple procedural scripts) – KareemElashmawy Jun 07 '17 at 00:39
  • @le_m I've updated it to clarify. Thanks for pointing that out. – KareemElashmawy Jun 07 '17 at 00:42
  • 1
    You might be better off looking for a non-code answer, e.g. using the dev-tools or some static code analysis etc. See https://stackoverflow.com/questions/2226007/fetching-all-javascript-global-variables-in-a-page for hacks trying to attempt what you want in plain JS – le_m Jun 07 '17 at 00:43

2 Answers2

2

I'm not sure a count of global variables is, of itself, a useful indicator of anything. You should do some analysis to work out which are created by code, which are host specific and which are related to the environment (e.g. DOM).

In a browser, the window object is a synonym for the global object, hosts are allowed to add properties to it (e.g. window.name) as well as define properties on its prototype (if it has one).

Also, all element IDs are created as properties of window (you can blame Microsoft and IE for that), so if there are lots of element IDs then there'll be lots of global properties.

Anyway, below are two ways to count the own enumerable properties of the global (window) object. It uses an IIFE so it doesn't create any properties itself.

// Create 3 global properties
var x, y, z;

(function(global) {

  // for..in with hasOwnProperty check
  var count = 0;
  for (var prop in global) {
    if (global.hasOwnProperty(prop)) {
      count++;
    }
  }
  console.log('for..in count: ' + count +
  
            // Direct count using Object.keys
            '\nObject.keys  : ' + Object.keys(global).length);
            
// Pass global (window in a browser) object to function
}(this));

So an approach to testing for code-created variables in a browser may be to:

  1. Count the number of global properties in an "empty" document, that should be the default host-defined set
  2. Count the total number of global properties in the suspect document
  3. Count the number of elements in the document with an ID

So the number of code-created globals should be the result of item 2 - (item 1 + item 3).

You can count the elements with an ID something like:

var allEls = document.getElementsByTagName('*');
var idCount = 0;

for (var i=0, iLen=allEls.length; i<iLen; i++) {  
  if (allEls[i].id != '') {
    ++idCount;
  }
}

or:

[].filter.call(document.getElementsByTagName('*'), function(el) {
  return el.id != '';
}).length;
RobG
  • 142,382
  • 31
  • 172
  • 209
1
var count = 0;
for( var x in window ){
    if( window.hasOwnProperty(x) ) count++;
}
console.log(count);
Gary
  • 13,303
  • 18
  • 49
  • 71
  • 3
    `Object.keys(this).length` might be simpler. ;-) – RobG Jun 07 '17 at 00:40
  • @RobG That worked; gary's answer came back with 0. Please post that as an answer – KareemElashmawy Jun 07 '17 at 00:43
  • Gary, your's returned 329 hits; @RobG's returned 327. – KareemElashmawy Jun 07 '17 at 00:45
  • Caveat: it's Object.keys(window).length not Object.keys(this).length – KareemElashmawy Jun 07 '17 at 00:46
  • @Gary— [*Object.keys*](http://www.ecma-international.org/ecma-262/7.0/index.html#sec-object.keys) returns own enumerable properties, effectively the same as *for..in* with a *hasOwnProperties* check. And *this* returns the global object, which is synonymous with the *window* object, but works in more environments than just browsers. – RobG Jun 07 '17 at 00:46
  • @KareemElashmawy—you might want to try `window === this` in global context. ;-) – RobG Jun 07 '17 at 00:48
  • run in global: `let test=1;console.log(test, window.test);` so you will have global scope variable without assigning it to window context; – zb' Jun 07 '17 at 00:54