Understanding top level window property - javascript

I get a js error when I declare the following script.
<script>
window.onload=init;
init = function(){alert("Yahoo!");}
</script>
It works when I declare init as:
<script>
window.onload=init;
var init = function(){alert("Yahoo!");}
</script>
Shouldn't the top level init should implicitly become the property of window object? Please help me understand the concept.

JavaScript tracks variables and function declarations before executing the code. Lots of languages do this, actually, so it's a good thing to get used to.
It does not, however, track assignments. That counts as executing the code. Even though when a variable that is not defined is assigned, it becomes a property of window, it is not a variable! It can be deleted from window, unlike real variables.
var i = 2;
n = 2;
delete window.i; //false
delete window.n; //true
Thus, they can not be used before they are defined like variables. Instead, they must be defined first, and then used. Otherwise, they will not be defined.
//OK, but not recommended because init is now not a variable. It makes more sense to make init a variable instead.
init = function(){alert("Yahoo!");}
window.onload=init;

<script>
window.onload=init;
var init = function(){alert("Yahoo!");}
</script>
This is organized by Javascript as such (variable declarations first):
<script>
var init;
window.onload=init;
init = function(){alert("Yahoo!");}
</script>
Thus, init is present when used for onload.
The one without the var doesn't include a variable declaration but an assignment to a property of window. Assignments are not changed during preprocessing. So, nothing named init is found and execution fails.

this is related to the fact that javascript engine makes two passes over a function. at first pass, it moves all the local variables to the top of the function, and in second pass it runs the function.
So, when you define init with var, it is a local variable, therefore defined in the first pass and successfully run in the second pass.
I'm not sure if i could make it clear, but if you want to get more information on this topic, it was very well covered in Single Page Web Applications by Michael S. Mikowski and Josh C. Powell.

Related

Why JavaScript file starts with (function (undefined)? [duplicate]

Have you ever taken a look under the hood at the jQuery 1.4 source code and noticed how it's encapsulated in the following way:
(function( window, undefined ) {
//All the JQuery code here
...
})(window);
I've read an article on JavaScript Namespacing and another one called "An Important Pair of Parens," so I know some about what's going on here.
But I've never seen this particular syntax before. What is that undefined doing there? And why does window need to be passed and then appear at the end again?
The undefined is a normal variable and can be changed simply with undefined = "new value";. So jQuery creates a local "undefined" variable that is REALLY undefined.
The window variable is made local for performance reasons. Because when JavaScript looks up a variable, it first goes through the local variables until it finds the variable name. When it's not found, JavaScript goes through the next scope etc. until it filters through the global variables. So if the window variable is made local, JavaScript can look it up quicker.
Further information: Speed Up Your JavaScript - Nicholas C. Zakas
Undefined
By declaring undefined as an argument but never passing a value to it ensures that it is always undefined, as it is simply a variable in the global scope that can be overwritten. This makes a === undefined a safe alternative to typeof a == 'undefined', which saves a few characters. It also makes the code more minifier-friendly, as undefined can be shortened to u for example, saving a few more characters.
Window
Passing window as an argument keeps a copy in the local scope, which affects performance: http://jsperf.com/short-scope. All accesses to window will now have to travel one level less up the scope chain. As with undefined, a local copy again allows for more aggressive minification.
Sidenote:
Though this may not have been the intention of the jQuery developers, passing in window allows the library to be more easily integrated in server-side Javascript environments, for example node.js - where there is no global window object. In such a situation, only one line needs to be changed to replace the window object with another one. In the case of jQuery, a mock window object can be created and passed in for the purpose of HTML scraping (a library such as jsdom can do this).
Others have explained undefined. undefined is like a global variable that can be redefined to any value. This technique is to prevent all undefined checks from breaking if someone wrote say, undefined = 10 somewhere. An argument that is never passed is guaranteed to be real undefined irrespective of the value of the variable undefined.
The reason to pass window can be illustrated with the following example.
(function() {
console.log(window);
...
...
...
var window = 10;
})();
What does the console log? The value of window object right? Wrong! 10? Wrong! It logs undefined. Javascript interpreter (or JIT compiler) rewrites it this way -
(function() {
var window; //and every other var in this function
console.log(window);
...
...
...
window = 10;
})();
However, if you get the window variable as an argument, there is no var and hence no surprises.
I don't know if jQuery is doing it, but if you are redefining window local variable anywhere in your function for whatever reason, it is a good idea to borrow it from global scope.
window is passed in like that just in case someone decides to redefine the window object in IE, I assume the same for undefined, in case it's re-assigned in some way later.
The top window in that script is just naming the argument "window", an argument that's more local that the global window reference and it what the code inside this closure will use. The window at the end is actually specifying what to pass for the first argument, in this case the current meaning of window...the hope is you haven't screwed up window before that happens.
This may be easier to think of by showing the most typical case used in jQuery, plugin .noConflict() handling, so for the majority of code you can still use $, even if it means something other than jQuery outside this scope:
(function($) {
//inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
Tested with 1000000 iterations. This kind of localization had no effect in performance. Not even a single millisecond in 1000000 iterations. This is simply useless.

Declare variable so that would be it visible in global context but not belong to window or gett

I need to emulate in firefox the behavior of activeXobject in last versions of ie. I write addon with contentScript and want to implement to pages such variable. It is exactly what I want - It is a challenge in itself.
Example of IE 11 working code:
if (window.ActiveXObject == undefined) {
var but = new window.ActiveXObject; // [ActiveXObject object]
}
I need exactly same behavior in firefox with my variable
For example what i want
<script>
console.log(window.variable) // undefined
console.log(new window.variable); // [object Variable]
console.log(new variable) // [object Variable] if not possible previous string
</script>
for solving, you can change the addon sdk or a browser source, change realization of all getters or something else
In browser Javascript, there is no such thing as a global variable that is not a property of the window object. So, if that's truly what you are trying to do, then it cannot be done. Yes, you might be able to create a getter on the window object with Object.defineProperty(), but that's still a property on the window object so I'm not sure how that helps you.
Likewise, there is no structure in Javascript such that:
window.ActiveXObject === undefined
and this works:
var x = new window.ActiveXObject;
Javascript just simply doesn't work that way. The property either exists or it doesn't. It can't be undefined for one way of accessing it and defined for some other way of accessing it.
You might also be able to create the property on the window object so it is not enumerable if you want it to be less visible for some reason.
If you explained what you're really trying to accomplish, there may be some work-arounds by enclosing the relevant code in a closure and defining the variable in the closure, but without knowing more details about what the actual problem to be solved is, we can't help more specifically than that.
If you just want the variable defined for YOUR code only, then you can just put it in a closure:
(function() {
var myVar = "foo";
// other parts of your code
// elsewhere in your code
console.log(myVar);
})();
Your code can treat it like a global, but it's really not a global, it's just defined within the scope that your code lives and not available to any other code outside this scope.
Theoretically, this is possible with lexically declared variables in ES6:
let variable = 5;
console.log(variable); // 5
console.log(window.variable) // undefined
However, the current let support in FF is not as advanced, and still treats this a property of the global object.
If the variable only needs to be accessible by your project code, wrap all of your project code in a self executing anonymous function.
(function(){
var internalGlobalVar = "some value";
//All your code gets wrapped in here...
})();
Then if you tried to alert(window.internalGlobalVar) you would get undefined.
We use google closure compiler with plovr and wrap all of our code in a self executing anonymous function so basically all of our global variables are project scope, not on the window "output-wrapper": "(function($){%output%})(jQuery);"

Javascript: is the Windows object a default object?

First time poster. I tried to search for answer before posting.
I'm new to javascript, coming from a Delphi/pascal background. I am used to things having to be explicitly spelled out. When I see code that includes setTimeout or setInterval (see here:
http://www.w3schools.com/js/tryit.asp?filename=tryjs_setinterval1), I notice that it just looks like an intrinsic function. But I think it is actually a method of the Windows object.
So it looks like the "window." part is optional. Is this somethign specific to the Window object? Or will any method that is specified without the name of it's containing object be recognized in javascript? And what would happen if there was another variable in the global scope that had a method also named setTimeout? How would the compiler/interpreter know which one to use?
Thanks so much,
Kevin
In Javascript, there is something called the Global scope. On Browsers, the global scope object is window. If you create a variable outside of a function, it goes by default into the global scope, which is window.
When invoking a method or referencing a variable on the window object, it's optional to include window.
its not windows its window (no 's' at end).
As far as i know javascript have 3 scopes local, [clouser], global
Every variable or function is first looked up in local scope, then clouser and finally if not found anywhere in between it will checked in global scope.
As in image you will see global scope is shown as Window object which mean whatever goes in global scope goes in window object.
copy paste below code in chrome devtools console
function outerFunction() {
var a = 10;
debugger;
function innerFunction() {
'use strict';
var b = 10;
debugger;
console.log(a);
}
innerFunction();
}
outerFunction();
on 1st debug
on 2nd debug

How do you load 2 javascript files that could have common variables between them and accessing it on a HTML page?

I got this HTML page. I wanna access variables from 2 javascript files that has common variables. I gotta get values from these variables pertaining to the respective javascript. I tried loading them using <script> but when i access the js variables, it only get the values from the last js file, in other words, the last loaded js file overwrites the variable values and only these values are available to access. I'd really appreciate help on this one.
Thanks!!!
You need to namespace your variables or use variables with different names. What it sounds like you're doing is the equivalent of:
var x = 'foo';
var x = 'bar';
console.log(x);
> bar
Which should make sense. If you use namespaces though, things will work better for you. Consider two files, script-1.js and script-2.js:
// script-1.js
var s1 = {
x:'foo'
}
// script-2.js
var s2 = {
x:'bar'
}
...then...
console.log(s1.x);
> foo
console.log(s2.x);
> bar
That's a rather trite example, of course.
EDIT
If you can't change the files themselves do this - save off the values to some other name/object after loading script-1 but before loading script-2:
<script type="text/javascript" src="script-1.js"></script>
<script type="text/javascript">
var s1 = {
// Save off values here
x:x,
y:y
}
</script>
<script type="text/javascript" src="script-2.js"></script>
// Then...
console.log(s1.x); // will output the value from script-1.js
console.log(x); // will output the value from script-2.js
Not pretty, but should work fine.
If your problem is that your variables are colliding, and you want their values maintained separately, you should wrap the code in each file in a closure. Here you can apply the Immediately-Invoked Function Expression pattern.
(function() {
// your code here
// all of it!
}());
This prevents global variables altogether, and if you don't need to share anything across files, this is the way to go.
If you need to create a shared global, declare it this way:
var x = x || {}; // empty object as an example value
Do that at the beginning of each file. If x is new, it will be declared. If it has already been declared, it will retain its previous value.
You can do the same thing using namespaces, which I highly recommend as an easy way to reduce global variables.
var APP = APP || {};
APP.x = APP.x || {}; // example property of APP, in this case initializing an object
You can always combine techniques too. Setup a namespace object outside a closure, and access them within. This way you only expose one global and limit the scope on everything else.
I hope that helps!
If you have some control over the javascript files, Madbreak's answer is they way to go: whenever you define a javascript library you should be using anonymous functions and namespaces to avoid collisions.
Otherwise, though, you could load them asynchronously and eval them one at a time (There may be a less evil way to do this, but I'm not aware of it) - that way you can use the first in the callback of the download before it is overwritten by the second. If you need them both long term, though, you might be out of luck.
If you need one to run before the other, though remember that you'll need to load the second in the callback of the first download (where doesn't matter unless you're doing more async stuff) otherwise it's a race condition as to which will go first.

Watching a variable in an anonymous function in JavaScript

I want to determine when a particular variable is changed. I have had great success using this code to watch any property of any object that I can access, but can it be used for a variable declared like this?:
$( // line 1
function(){ // line 2
var A; // line 3
// ... lots of code that uses A as if it were a global. I wanna see what part of this code sets A ...
} // line 5999
); // line 6000
Surely A does not end up as a property of window. Is it perhaps a property of the anonymous function object which spans lines 2 thru 5999? So if I name the function so I can reference it am I able to use watch on the A var/prop somehow?
What other methods are available to me to figure out where the var gets set?
This might seem bit insane but, with a little modification, you'll be able to watch the variables pointer.
(function() {
window.ox = x = {};
x.y = 5;
})();
alert(ox.y);
This pulls it into the global territory, and should allow you to observe variable x from the global variable ox.
​
You can't use Object.prototype.watch on that variable, simply because it's a variable, not an object property. Regardless of its scope (which is the anonymous function you mentioned).
If you're trying to do that for debugging purposes, I believe you can watch it from your browser's developer tools.

Categories

Resources