8

Given that my plugin could be run on any JS engine (in a browser or not),

  • How does one know that some variable is actually the browser window object.

    Like how do I know if someVar references the browser window object. Is there something in window that I can check if it is really the browser window object?

  • And how to check if the browser window object actually exists and not just some window variable containing an object.

    Suppose you can't tell if someVar is window by itself, and you want to match it against the real browser window object like someVar === window, how do you get window that you are sure it is the browser window and not some other object from an outer scope named window, or some other global from another environment?

Just to clarify a bit more:

  • I'm not looking for the global of the environment. I'm looking for the browser window object specifically.
  • I'm not checking if the script is running on the browser.

I can't do something like if(!window) since window could just be another object declared somewhere outside the scope.

function someFunction(){
  var window = {foo:'bar'};

  (function(){
    console.log(window); //{foo:'bar'}
  }());
}

I can't check if(window.window === window) since I can also do self referencing, and like said earlier, window could be an object from an outer scope:

var bar = {};
bar.bar = bar;
bar.bar.bar.bar.bar.bar === bar; //true

And the following may not work since the script could be wrapped or concatenated within something other than the global space. this could also be modified with calls like call(), apply() or bind().

//Stand-alone, I can assume window is global since "this" is the global in global space
(function(window){
  //window may not be window
}(this));

//But when this happens
someNamespace.someFunction = function(){

  (function(window){
    //window may not be window
  }(this));

}

//or this:
someNamespace.someFunction.call({});

I have a feeling that this is a duplicate, but I couldn't find where I first saw it.

Joseph
  • 117,725
  • 30
  • 181
  • 234
  • possible duplicate of [How to check whether a script is running under node.js?](http://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js) – Andy Ray Jul 09 '13 at 08:12
  • It sounds like you want to determine whether your code is running in a browser or not by checking if window exists. You could try looking for features that a browser might implement as part of window such as window.location.href, but of course even this is not fail safe. How about determining if you can return a valid userAgent string? – Matthew Layton Jul 09 '13 at 08:16
  • Would `(function(){return this}).call(null)` always work? – John Dvorak Jul 09 '13 at 08:25
  • 1
    @JanDvorak: Nope. In ES3 environments it would, but ES5 changed the rules to say that the `thisArg` is not changed to the global object when `null` is explicitly passed. For instance, this will return null: `(function () { "use strict"; return (function(){return this}).call(null); })()`. – Andy E Jul 09 '13 at 08:30
  • @AndyE when is it changed to `thisArg`, then? Can a similar approach be used? – John Dvorak Jul 09 '13 at 08:31
  • @JanDvorak: the only way to get the global object from anywhere in strict mode is to use the approach in alex's answer or a "variant" eval approach like `Function('return this')()`. – Andy E Jul 09 '13 at 08:40
  • @AndyRay That answer accepts both `global` and `window` as `root`. How do you know if the global object is the browser `window` object? – Joseph Jul 09 '13 at 13:04
  • @series0ne Nope, I'm not checking if the script is running in the browser, I'm checking if `window` is the browser `window` object and not some other object named `window`. – Joseph Jul 09 '13 at 13:05

6 Answers6

4

This will not only test for current window, but for window in general:

    if (window.toString() === "[object Window]") {
         // your code here
    }

[edit]

toString() object prototype was available from JavaScript initial version 1.0 and was an old fashioned way to check for the "class". As well as the method mentioned in another answer to this question - to check for the unique object propert, which is faster to execute than string comparison.

Since JavaScript 1.4 (ECMAScript 3rd edition 1999) we are able to utilize instanceof operator to check for the object Class which is the right method for this task.

    if (window instanceof Window) {
         // your code here
    }
stamat
  • 1,832
  • 21
  • 26
Lex Podgorny
  • 2,598
  • 1
  • 23
  • 40
3

You can get the global object like so...

var global = (1,eval)("this");
alex
  • 479,566
  • 201
  • 878
  • 984
  • Is it possible without `eval` (or `new Function`)? – John Dvorak Jul 09 '13 at 08:24
  • @JanDvorak: I'm pretty sure it's not. – Andy E Jul 09 '13 at 08:33
  • 1
    I can't get part with `1` char. We actualy run `eval` on `"this"` string. How `1` involved here? – Tommi Jul 09 '13 at 13:17
  • 2
    @tommi it's just a method of making an indirect call to *eval()*. The 1 isn't relevant (it could be any valid expression), what matters is that you don't call *eval()* directly. This is how you can evaluate code in the global scope from anywhere. It doesn't work in IE8 and lower though. – Andy E Jul 09 '13 at 14:41
1

How about

function isWindow() {
    _test = 42;
    return window && window._test == 42
}
georg
  • 211,518
  • 52
  • 313
  • 390
1

I found it while understanding creating instances through

var MyExampleInstace = function MyExampleInstace() {
    console.log(this); // returns undefined in strict mode
    // in not strict mode it will return Window 
}

new MyExampleInstace(); // will not return and error (this will be fine)

I wanted to create an error like

throw new Error('Please use "new" keyword');

When somebody tries to call MyExampleInstance not as instance but as simple function like:

MyExampleInstance(); // console should show "Please use "new" keyword

So the final result was:

var MyExampleInstace = function MyExampleInstace() {
    if (this === undefined || this instanceof Window) throw new Error('Please use "new" keyword');
}

To check the object is the object of some "kind" the most simple way I found through

// myVar could be "this" or every var u need
// That's also opens the way to check the object instance of your MyExampleInstance
myVar instanceof Window

https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/instanceof

Aleksey Spirin
  • 170
  • 2
  • 8
0

You can check it if you use some methods supported just by the object window. For example postMessage:

(function(o){ 
 if(!!o.postMessage) console.log("This is my window"); 
 else console.log("This isn't my window");
})(window);  
-1
if( this.window === this )

    

David Thomas
  • 249,100
  • 51
  • 377
  • 410
Andy Ray
  • 30,372
  • 14
  • 101
  • 138
  • "the script could be wrapped in something other than the global space" – John Dvorak Jul 09 '13 at 08:22
  • then save a reference to `this` at the top of the file. jesus. – Andy Ray Jul 09 '13 at 08:27
  • "the script" refers to the entire file, I assume. No need to be rude. – John Dvorak Jul 09 '13 at 08:28
  • In which case I'm afraid the asker's script is not a file. Or maybe it is a file that is included somewhere. Or maybe it's an environment where "all files execute in the global context" doesn't hold. Or maybe it's an environment where the concept of a file doesn't exist. There is a lot of environments, and you can't just assume the asker will be able to place anything anywhere but in the script itself, and "the script could be wrapped in something other than the global space". – John Dvorak Jul 09 '13 at 20:00
  • Our manager at a company I formerly worked really likes configurable things, and he wanted things to be done as fast as possible. Of course, coding for a database access is faster than coding for a file access. Well, it turns out that javascript is not always stored in a file, and it is by far not always injected to the global scope. Sure, there are reasons to not do that, but PHP injection and Javascript injection by the administrators are better than having to code one hour longer. And, sometimes these scriptlets end up being _not_ inside the global scope, but, say, a jQuery `click` handler. – John Dvorak Jul 10 '13 at 05:01