javascript window.onload scope - javascript

Can someone explain why the alert returns "undefined" instead of "hello"?
window.onload = function() {
var a = 'hello';
alert(window.a);
}

variable 'a' is not part of window in your context.
a is scoped to the anonymous function you've assigned to onload.
you COULD add a as a member of window if you wanted:
window.onload = function() {
window.a = 'hello';
alert(window.a);
}
but i'd suggest against doing so.

"Named variables are defined with the var statement. When used inside of a function, var defines variables with function-scope." - (source)
To be accessible globally, and particularly to make a a member of the window object, alter your code in this way:
var a; // defined in the global scope
window.onload = function() {
a = 'hello'; // initialized
alert(window.a);
}
Or in this way:
var b = 'world'; //defined and initialized in the global scope
window.onload = function() {
alert(window.b);
}

Related

not able to execute the named functions that are also refereed

i'm learning about functions. i'm confused in one scenario.
suppose i have three functions
<script>
var fnRef = function() {
console.log("i'm function with no name but refered to fnRef");
};
var funRef2 = function test() {
console.log("im test reffered to funRef2");
};
function test2() {
console.log("i'm test2 named function")
};
</script>
fnRef, fnref2 and test2 will be assigned to window as a property as fnRef and fnRef2 are variable and test2 is named function that act as variable.
but why test2 is not assigned to the global object(window) when refered by funref2? and why i'm not able to execute test(); can someone tell me what is happening in detail.
The named function expression is useful so you can access the function inside it's own scope without using arguments.callee, and it also makes it easier when debugging as the name can be seen in stack traces, breakpoints etc.
This name is then local only to the function bodys scope, meaning
var test1 = function test2() {
if (something) test2(); // available in this scope only
}
test2(); // not here
You can't call the function by it's name, only by the variable it's assigned to, as the functions name is limited to the functions scope when it's a function expression.
When defining a function declaration, the name is assigned to the current scope, and hoisted, so this
var bar = test();
function test() { return 'foo'; }
is more or less turned into this
var test = function() { return 'foo'; }
var bar = test();

How are both of these referring to the same variable?

I have a very confusing situation...
(function sayStuff(){
this.word = "hello2";
(function (){
console.log(this.word);
}())
}())
var myObject = {
word: "bar",
func: function() {
(function() {
console.log(this.word);
}());
}
};
myObject.func();
Outputs
hello2
hello2
How is this happening? How can the closure on the 'func' of myObject actually see the variable that is referenced in sayStuff()? I thought IIFE were meant to protect internals from Global scope?
In both cases, this is window, the global default context replacing the one you don't provide when you call the internal function expressions.
If you want to keep the context, don't use IIFE internally or call them with the context :
(function sayStuff(){
this.word = "hello2"; // still this is window, use var if you don't want that
(function() {
console.log(this.word); // window.word
}).call(this); // well, this is window...
}())
var myObject = {
word: "bar",
func: function() {
(function() {
console.log(this.word); // myObject.word
}).call(this);
}
};
myObject.func();
IIFE only hide locally scoped variables (i.e. those created with the var keyword).
All your functions that touch this.word are invoked in the global context (i.e. not as methods of an object, not with the new keyword and not with apply, call or bind), so this is window in each case. You are dealing with global variables.
If you wanted a private variable you would do something more like this:
(function (){
var word = "hello2";
(function (){
console.log(word);
}())
}())

Declaring two variable with the same name

Is it possible to call the same name variables which set outside of the function?
var a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
var a = $(window).height(); // Not this one
alert(a);
}
FIDDLE
In this case, you have actually redefined the value of a. There is absolutely no way of referencing a different variable with the same name, as it just acts as a redefinition.
If you want to declare a global variable you can do so by
window.varname="This is a global variable";
And you can access the same by
alert(window.varname);
Now you can also have a local variable inside a function with the same name
var varname="This is a local variable";
And you can access it normally.
Here's your code so that you can access the global variable not the local one.
var p = ['foo',''];
window.a = $(window).width();
if(!$.isFunction(p)){
var a = $(window).height();
alert(window.a);
}
In a code snippet such as yours, the variable a is being redefined. This is because an if statement doesn't create another scope for variables. However, functions do.
In a case like this:
var a = 0; // global
function doStuff() {
var a = 10; // local
alert(a);
alert(window.a)
}
alert(a);
doStuff();
alert(a);
inside the function doStuff, the variable a is being redefined. This snipped will therefore alert the numbers 0, 10, 0, 0. This proves that the global variable is not redefined inside the function, as printing a after calling doStuff doesn't change the value of a in the global scope.
The variable a outside of the function can be accessed, as any variable not declared in a non-global scope is placed inside the window object. However, if using this snippet (which calls an anonymous function, creating a new scope):
var a = 0; // global
function doStuff() {
var a = 10; // local
alert(a);
alert(window.a)
function() {
var a = 20; // even more local
alert(a);
alert(window.a);
}();
}
alert(a);
doStuff();
alert(a);
you cannot access the value of a inside the doStuff function. You can still access the global variable using window.a.
In your case, however, the if statement does not create a new scope, therefore you are redefining the variable a to the new value $(window).height().
Example:
var a=10;
if(true){
var a=5;
}
alert(a)// it will return a=5;
var a=10;
var a=5;
//both are same way assign value
In js if statement is not scope it visible every where with in function . you have to change the variable name
There is no blockscope in JavaScript (at least up until ES6).
Like you seem to expect from the if block. See
What is the scope of variables in JavaScript?
for an excellent summary of scopes that do exist in JavaScript.
Beware of Hoisting
Furthermore, you shouldn't sprinkle your var declarations through your code, but explicitly put them in the top of your function. That is where Javscript will hoist them anyway:
# so if you have a function like this
var i = 5;
function testvar () {
alert(i);
var i=3;
}
testvar();
# the alert window will contain undefined.
# because internally, it's been changed into this:
var i = 5;
function testvar () {
var i;
alert(i);
i=3;
}
testvar();
Minimize use of the global scope
Read
What is meant by “leaking” into global scope?
And listen to what Doug Crockford has to say about it. Actually, take an hour and watch the whole talk.
You can do it like this:
var p = ['foo',''];
var a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
(function(b){
var a = $(window).height();
alert(b);
})(a);
}
No need to use the global scope, just create an anonymous function and call it with a as the argument. Inside the function b is a reference to the a variable outside the function.
It is a good practice not to modify the window object in javascript to write clean and maintainable code.
Less bugs and problems. I mean, never do the window.a thing. Is evil for your code.
No, you can't because of you have redefined the variable name in the same scope and beacuse of the hoisted variables your code will be interpreted by javascript in the following mode:
var p, a;
p = ['foo',''];
a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
a = $(window).height(); // Not this one
alert(a);
}
Now you can easly see that the variable a will be replaced and not created
JavaScript has two scopes: global and local. In your example a is in the global scope both times so you are just redefining it.
However you can specify skip a variable in local scope and get the one from global. Consider this example:
var a = 1;
function foo () {
var a = 2;
console.log("var a is: " + window.a);
console.log("local var a is: " + a);
}
foo ();
Will log "var a is: 1"\n"local var a is: 2\n" to the console. This is about as close as it gets to what you need
var abc = new Array();
abc[0] = 'str1';
abc[1] = 'str2';
Use array in this case
Try this (pattern)
var p = ['foo', ''];
var a = function (name) {
return (
name === "height"
? $(window).height()
: (name === "width" ? $(window).width() : name)
)
};
if (!$.isFunction(p)) {
// `$(window).width()` , `$(window).height()`
alert( a("width") + "\n" + a("height") );
}
jsfiddle http://jsfiddle.net/guest271314/2tuK4/

Scope of self-invocation function in Javascript

Why does self-invocation function inside a function don't get the scope of the outer function in JavaScript?
var prop = "global";
var hash = {
prop: "hash prop",
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop);
})();
}
};
var literal = {
prop: "object"
};
hash.foo();
// hash prop
// global
hash.foo.call(literal);
// object
// global
Looks like altering the scope of the outer function has no effect on the scope of the inner self-invocation function.
PS: The question is not about how to alter the scope of the inner function. But what is the proper explanation in the "Javascript language" perspective? Does all self executing functions have 'global' scope by default? If so, why?
Your problem is the this and what it references:
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop); <--- this does not reference to foo here, but instead it refers to the window object
})();
}
You need to keep a reference to the outer this:
foo: function(){
console.log(this.prop);
var that = this;
(function bar(){
console.log(that.prop); <--- tada!
})();
}
Update
Some explanation. It's all about how JavaScript determines the context when invoking a function.
function Test() {
this.name = "Test";
this.bar = function() { console.log("My name is: "+ this.name);}
}
function Blub() {
this.name = "Blub";
this.foo = function() { console.log("My name is: " + this.name);}
}
var a = new Test();
var b = new Blub();
// this works as expected
a.bar(); // My name is: Test
b.foo(); // My name is: Blub
// let's do something fun
a.foo = b.foo; // make an educated guess what that does...
a.foo() // My name is: Test
Huh? Aren't we referencing the method of Blub? No we're not. We are referencing the unbound function of Blub.
JavaScript binds on . (dots) and based on that it decides waht the value of this should be.
Since you're not calling your anonymous function on an object (therefore no .) it will make this reference to the global object, which is - in case of the browser - the window object.
Another example (one might think this would work):
var str = "Hello World";
var ord = str.charCodeAt; // let's make a little shortcut here.... bad idea
ord(0) // no dot...
Instead of the char codes that are in str we get the ones that are in the global object, of course that's not a string so charCodeAt calls toString on which results in "[object DOMWindow]"
You are not applying any object as the this context when you call the inner function, so it gets this set to window by default. If you wanted to call the closure with the same this as the outer function, you would have to do:
(function bar(){
console.log(this.prop);
}).call(this);
Or:
var that = this;
(function bar(){
console.log(that.prop);
})();

HTML JavaScript Include File Variable Scope

If I include a JavaScript file in my HTML page, do the variables declared in my JavaScript file also have scope in my <script /> tags in my HTML page? For example, in my included JS file, I declare a variable:
var myVar = "test";
Then inside my HTML page, what will this produce (if it's after my include script tag)?
alert(myVar);
If you declare the variable outside of any function as
var myVar = 'test';
or at any location as
myVar = 'test';
or
window.myVar = 'test';
It should be added to the Global Object (window) and be available anywhere as
alert(myVar);
or
alert(window.myVar);
or
alert(window['myVar']);
It will produce an alert containing "test".
All variables declared at the top level in JavaScript share the same scope. If you want to use variables in one file that won't clash with another, then you can use an anonymous function to introduce a new scope:
var myVar = "something else";
(function () {var myVar = "test"; alert(myVar)})();
alert(myVar);
edit: As BYK points out, you can expand this into something that resembles a full fledged namespace, by assigning an object literal:
var MyNamespace = (function () {
var myVar = "something";
return { alert: function() { alert(myVar) },
setVar: function(value) { myVar = value } }
})();
When you declare a variable or a function in your code, you're creating a property of window. Consider these examples:
var a = 'Cow';
alert(window.a); // Cow
alert(this.a); // Cow
alert(a); // Cow
If you declare a variable inside a function, your variable won't be accessible from outside of it unless you add it to the window object:
function lalala() {
alert(a); // still Cow
a = 'Pig'; // We're tired of cows by now. Let's make it a pig.
var b = 'Sheep';
}
lalala();
alert(a); // Pig
alert(b); // undefined, since b is declared in the lalala scope
Thus, your example would alert test.

Categories