local variables in a function [duplicate] - javascript

This question already has answers here:
JavaScript: Reference a functions local scope as an object
(5 answers)
Is there a Javascript variable that represents local scope? Like global?
(1 answer)
Closed 8 years ago.
I know that variables are properties of other objects. For example:
var myVar = 'something';
is a property of the window object (if it is in the global scope of course).
if I want to find the variable's object, I just use the this variable. But:
function f() {
var myVar2 = 'something';
}
Which object does myVar2 belongs to? (myVar belongs to window object, but what about myVar2?)
I would like to know that, thanks.

It doesn't belong to an object. It belongs to the scope of the function f. You access it by doing myVar within f. You cannot access it outside of f.
If you did
function f() {
this.myVar = 1;
}
now you can do
var myF = new f();
myF.myVar
indeed, this how user defined objects are sometimes defined.

myVar2 belongs to the local scope (of f), and myVar the global scope.

var does some interesting things. var statements are hoisted to the top of their functional scope. The var's functional scope is whatever function it happens to be in.
JavaScript doesn't have block-level scope, which means that:
(function () { //a closure to create new scope
var foo;
foo = 1;
if (condition) {
var bar;
bar = 3;
}
}());
...is equivalent to...
(function () {
var foo,
bar;
foo = 1;
if (condition) {
bar = 3;
}
}());
If the var statement has no parent, it will instead add the variable as a property to the global context, which in web browsers happens to be window.
This is the only time that using var will create a property. If want to create a property of an object, you simply have to set it:
(function () {
var foo;
foo = {};
foo.bar = 'baz'; //this creates the `bar` property on `foo`
}());
JavaScript is a prototypal language with prototypal inheritance. Functions are first-class objects (because JavaScript isn't racist against functions). This means that functions can be used just like any other object.
You can set them:
(function () {
var foo;
//foo is now a function
foo = function () {
alert('Hello World');
};
}());
You can set properties on them:
(function () {
var foo;
foo = function () {
alert('Hello World');
};
foo.bar = 'baz'; //this works just fine
}());
You can even pass them as parameters:
(function () {
var foo,
bar;
foo = function () {
alert('Hello World');
};
bar = function (c) {
c();
};
bar(foo); //guess what this does?
}());
Another cool thing that functions do, is they act as constructors. All functions are inherently constructors, you just need to call them using the new keyword:
(function () {
var foo; //case sensitive
//it doesn't matter whether you use `function Foo`
//or `var Foo = function...`
function Foo() {
alert('Hello World');
}
foo = new Foo();
foo.bar = 'baz';
}());
The important detail in using constructors is that the function's context (this) will be set to the object created by the constructor. This means that you can set properties on the object within the constructor:
(function () {
var foo;
function Foo() {
this.bar = 'baz';
}
foo = new Foo();
alert(foo.bar); //'baz'
}());

Related

Way to understand this code. How is it working?

I was exploring scopes in javascript and came to know this problem. I don't understand how this problem is working.
function checkType() {
return foo;
foo = 10;
function foo() {};
var foo = 11;
};
console.log(typeof checkType())
My question is this how does javascript compiler decide to return function not variable. Any reference or explanation are welcome.
This is how the compiler will compile the above code..
function checkType() {
var foo = function() {}; /* function will be hoisted to the top,
and will be assigned to the variable as
the name is the same for the two.. */
return foo;
// Code will never reach here as you are returning before this
foo = 10;
foo = 11;
};
console.log(typeof checkType());
Functions which are defined using function() syntax will be hoisted, in this case, the nested function will be hoisted insde the checkType() and hence, the checkType() returns the function instead of the integer.
Note: Because the function was defined using function(){} syntax, it
was hoisted to the parent function scope, else, if the function was
defined using var foo = function() {} then the hoisting would not
have worked in the same way, your function would've returned undefined instead.
More reference on Scoping & Hoisting
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/
First all the function declarations are hoisted in a scope. So first of all the code moves the variable foo to the top of the scope and initialize its value to function.
The second declaration of variable is not hoisted because the function declaration is already hoisted. So the code is same as
function checkType() {
var foo = function(){}
return foo;
foo = 10;
foo = 11;
};
When we run a code there are two phase of it first is creation phase in this phase the syntax parser will read the code and hoist the function and variables, and second phase is execution phase in which the values are assigned to hoisted variables,
A point to note here is function are stored in memory during creation phase as it is where as the variables are hoisted but values
are not initialized ( which will be assigned during execution phase )
Compiler will treat your code like this after hoisting
function checkType() {
var foo = function() {}; //hoisted function
return foo;
foo = 10;
foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())
If you define your function as variable than it will be hoisted only but will not be initialized with value, you can see the below example
function checkType() {
return foo;
foo = 10;
var foo = function foo() {};
var foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())

Why can't I assign a function to a variable using prototype?

I keep on trying to assign a function to a variable and I keep getting a message saying foo is not a function. I am not sure why it is saying that. When I invoke the method by itself it works, but when I assign it to a variable it won't work.
Can anyone please help me figure this out? Thank you!!!
Below is my code:
function Test(){
function foo(){
return "foo";
}
this.bar = function () {
var foo = foo();
console.log(foo);
};
}
var test = new Test();
test.bar();
The culprit is this line var foo = foo();. The statement var foo is redeclaring the local foo variable. By the time you try to access it with foo() it has become an undefined variable.
Rename the variable or the function and everything works correctly.
Following code will work. As Now we are not trying to assign same function variable to variable.
The problem is because JavaScript is function scoped. It is failing because this.bar function will try to evaluate foo first and foo is name of variable in this function so interpreter will try to execute the foo but foo is variable in this scope it will not consider foo mentioned above. Hence it fails.
Where as foo1 will work because when interpreter hits the term foo1 it will look for current scope and all parent scopes and it will get it.
function Test(){
function foo1(){
return "foo";
}
this.bar = function () {
var foo = foo1();
console.log(foo);
};
}
var test = new Test();
test.bar();
Error is at this line
var foo = foo();
Your variable foo has the same name as the function, that hides the function outside.
Renaming it will resolve the error.
var foo1 = foo();
There error you're seeing is from this line:
var foo = foo();
When you use var there you are saying that foo is being defined for the current level of scope (this.bar) - meaning it won't bubble up to Test. You can either rename the variable to something else:
var result = foo();
console.log(result);
or just forgo that variable altogether like this:
console.log(foo());
totally your choice.
If you are learning how to create and work with JavaScript objects, you may want to rewrite your code like so:
// This function constructs the object when called with new
function Test(prop) {
// Some arbitrary property
if (typeof prop === "undefined") {
prop = null;
}
this.prop = prop;
}
// The two functions
Test.prototype.foo = function() {
return "foo";
}
Test.prototype.bar = function() {
var foo = this.foo();
console.log(foo);
}
// Create the object and call foo
var test = new Test('p');
test.bar();
All JavaScript objects inherit the properties and methods from their
prototype. Objects created using an object literal, or with new
Object(), inherit from a prototype called Object.prototype. Objects
created with new Date() inherit the Date.prototype. The
Object.prototype is on the top of the prototype chain.
From: http://www.w3schools.com/js/js_object_prototypes.asp

Why can JavaScript functions to be accessed Before they are defined? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can I use a function before it's defined in Javascript?
As would be expected, the following code throws an error because Foo is not defined:
window.Foo = Foo;
Also as expected, this throws the same error:
window.Foo = Foo;
Foo = function() {
...
};
Curiously, this works just fine:
window.Foo = Foo;
function Foo(){
...
};
How is this possible? Isn't JavaScript interpreted line-by-line?
Hoisting is only part of the story here.
First, to explain hoisting:
When you use var in a JavaScript program, you declare a variable. Wherever that variable is declared in a JS scope, it is hoisted to the top of that scope. JavaScript has only Global or Function scope; in the case of a function
function hoistAway() {
console.log(a);
var a = 5;
}
is equivalent to
function hoistAway() {
var a;
console.log(a);
a = 5;
}
As you can see, the declaration is hoisted, but the initialization is not. Thus, this code would log undefined on the console, rather than 5. However, it would be satisfied that a exists.
When you don't use var, the declaration is not explicit, so it doesn't get hoisted. Thus:
function hoistAway() {
console.log(a);
a = 5;
}
will result in an error message.
In your examples:
window.Foo = Foo;
Foo was never declared, so you get an error.
window.Foo = Foo;
Foo = function() {
...
};
Again, Foo was not declared, so no hoisting. For the record:
window.Foo = Foo;
var Foo = function() {
...
};
will not throw an error. However, only the declaration is hoisted, so if you did something like
var bob = {};
bob.Foo = Foo;
var Foo = function() {
...
};
then bob.Foo would be undefined. The special case of window.Foo = Foo is weird because Foo and window.Foo are the same in the Global scope.
Finally:
window.Foo = Foo;
function Foo(){
...
};
works, because function declarations (as opposed to function expressions) are also hoisted; both the name and the definition gets hoisted, so this would work as intended.
The script is parsed first, allowing your code to call functions that are defined later on.

Assigning a private variable to the value of a same-named variable from its parent scope

Can a private variable within a child scope be set to the value of a same-named private variable from its parent scope?
Consider the following:
var foo = 10;
function bar () {
var f = foo, foo = f;
return foo;
}
bar() // Returns 10
Can this be done without using the placeholder variable f?
var foo = 10;
function bar () {
var foo = foo;
return foo;
}
bar() // Want 10 but returns undefined.
I would like a solution that does not pass any arguments to bar. I realize that this isn't important for any reason other than aesthetics.
In the second case, global variable is not visible since there is a local variable having the same name. In other words, local variable hides the global variable.
var foo = foo;
The declaration of foo ends only after reaching ;. But trying to initializing foo to foo itself is undefined since it hasn't reached it's ending point of declaration.
Yes, but you'll have to explicitly reference foo off of the parent scope. Usually that will just be this, but you'll have to be careful in situations where your function may have been invoked via apply or call. This, for example, should work:
var foo = 10;
function bar () {
var foo = this.foo;
return foo;
}
bar(); // 10
Edit: I need to make a correction, per #Felix' comment. this will indeed usually refer to the global scope, rather than the parent scope. Consider this for example:
var x = 'global';
(function () {
var x = 'inner';
(function() {
var x = this.x;
console.log(x); // 'global'
})();
})();

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);
})();

Categories