Can functions access variables defined in its own parent function? - javascript

Mozilla's Developer Resource shows two contradicting explanation regarding the function scope.
Here
indicates that even though a "variable is defined in the same scope as the function calls", the code will throw an error because "it is not defined inside the function definitions".
Example)
function myBigFunction() {
var myValue;
subFunction1();
}
function subFunction1() {
console.log(myValue);
} //this will show a reference error
However, here indicates that a "function defined inside another function can also access all variables defined in its parent function and any other variable to which the parent function has access".
Example)
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
} //this is ok

In your first example
function myBigFunction() {
var myValue;
subFunction1();
}
function subFunction1() {
console.log(myValue);
} //this will show a reference error
here myValue is included in a function myBigFunction() so it has a block scope.
Block scope means any code within that block (here function defines the block) can use that variable if function contain another function(function definition) and inner function using that variable then it will be passed in a closure to inner function. 2nd scenario exactly same what I explained here.
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
} //this is ok
In above example num1 and num2 are declared in function getScore(), and it has inner function add() since add function using num1 and num2 it will be passed as closure to add() function and there won't be any error while accessing those variables.
but in first example the variable is accessed out of scope and as the variable accessed outside of that function it won't be accessible and it will throw reference error.
I hope the explanation clear your understanding. to understand it thoroughly go through JavaScript scope and closure concept.

The reason why the first example fails and the second 'works' has to do with scope and closure. You can think of a function's 'curly braces' as the enclosure around its scope - or sphere of influence.
The first example fails because myBigFunction()'s variable is not accessible to subFunction1()'s scope. myBigFunction() also doesn't wrap subFunction1() which would provide a closure. Check out closures here.
However, add() is declared within the scope of the getScore() function. getScore() 'wraps' add() - providing a closure so that add() has access to variables within getScore()'s scope.

Use the this keyword to get parent variable i.e.
var bar = function () {
this.foo = "example";//the only catch is you have to have the this key word when defining the term.
var subfunction = function () {
this.foo = "This an example!";
}
}
(Hope this helps!)

Related

Javascript: When putting an if in a function, is there anything that needs to be added?

I'm "newer" to JavaScript, and was wondering if anything needs to be added when putting an if in a Function. This is my code. I want to be able to use one function to call another function that alerts the page.
function Function() {
var var1 = Math.floor((Math.random() * 10) + 1);
document.getElementById("paragraph1").innerHTML = var1;
Functions();
}
function Functions() {
if (var1 == 1) {
Question1();
}
}
function Question1() {
alert("works");
}
Your problem isn't with if, but with variable scope.
Variables declared with var are local to the function, they can't be accessed from another function. You should pass the value as an argument to the other function.
function Function() {
var var1 = Math.floor((Math.random() * 10) + 1);
document.getElementById("paragraph1").innerHTML = var1;
Functions(var1);
}
function Functions(var2) {
if (var2 == 1) {
Question1();
}
}
function Question1() {
alert("works");
}
Quick lesson about variable scopes: Variables only exist in the scope they are defined in
Because of that, in your definition of Functions the variable var2 would be undefined.
Two solutions
Pass the variable through parameters, i.e when calling Functions, pass var2 through the parameters like Functions(var2), and the catch the value within the function body
Define var2 globally, so both functions can see the value. Although, this is often considered bad practice

Why can't you call functions declared inside parenthesis?

As far as I can tell, JS is function scoped and not block scoped, meaning objects declared inside (parenthesis) do not create a different execution context. However:
$('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
first();
});
Returns Reference Error function is undefined. The function first is being declared inside a parenthesis, so technically it should be available to other functions that call it from the scope it was declared at.
But this works:
var callDat = $('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
callDat.first();
});
My assumption is that since objects are functions, declaring a function inside an object can count as declared inside a different function scope even without curly braces. I however wish for a definitive answer on this.
In your second example, the first you're getting is not the one you've declared above - its the jQuery.first method available to all jQuery objects.
This is checkable - clicking "First" and then "Second" below does not output "first activated" from a click to the second button.
var callDat = $('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
callDat.first();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="firstBtn">First</button>
<button id="secondBtn">Second</button>
Returns Reference Error function is undefined. The function first is being declared inside a parenthesis, so technically it should be available to other functions that call it from the scope it was declared at.
No. Function declarations create a variable in the scope they are declared with which has the same name as the function. Function expressions do not, even if they are named function expressions. (Named function expressions to create a variable of that name inside their own scope).
Further reading: JavaScript function declaration syntax: var fn = function() {} vs function fn() {}
My assumption is that since objects are functions,
Functions are objects. The reverse is not necessarily true.
declaring a function inside an object can count as declared inside a different function scope even without curly braces
No, it can't.
In first example you actually do create a scope - this:
$('#firstBtn').click(function first() {
console.log("first activated");
});
is actually this:
(function first() {
console.log("first activated");
})
And as such is not available to other scopes
Now - if you'll declare it as such:
function first() {
console.log("first activated");
}
$('#firstBtn').click(first);
$('#secondBtn').click(function() {
console.log("second activated");
first();
});
you won't get the error
It's a "function literal" or "function expression" which only returns a function as a value, but does not define it in the surrounding function scope as a variable. It does, however, have its own scope. See my snippet below for something very interesting:
var counter = 0;
// function "b" is acting as a value to be given to "a"
var a = function b() {
alert(counter);
counter++;
// both "b" and "a" are accessible in here
if(counter < 3) b();
};
a(); // only a is accessible here
Because it's not obvious from the syntax, the form...
function func() { ... }
...may be replaced by the following to be more clear:
var func = function() { ... };

javascript closures still applies

If I have a function inside another function but the inner function doesn't use the outer function's variables, will the inner function still be a closure?
function someFunc(){
return function(){
\\do some more stuff
}
}
Whenever you see the function keyword within another function, the inner function has access to variables in the outer function.
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + tmp);
}
bar(5);
}
foo(2);
This will always alert 10, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.
For info about closures, refer: http://javascriptissexy.com/understand-javascript-closures-with-ease/

What is the exact use of closures in Javascript?

Hi still i'm not sure about the exact usage of using closures in javascript.I have idea about closures "A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain".But i don't know why we are using closures in javascript.
It allows you to succinctly express logic without needing to repeat yourself or supply a large number of parameters and arguments for a callback function.
There is more information available here: javascript closure advantages?
Imagine if instead of
alert("Two plus one equals" + (2+1) );
you'd be forced to declare a variable for every constant you ever use.
var Two = 2;
var One = 1;
var myString = "Two plus one equals";
alert(myAlert + (Two + One) );
You'd go crazy if you had to define a variable for every single constant before you can ever use it.
The access to local variables in case of closures is an advantage, but the primary role - usefulness - is the use of a function as a primary expression, a constant.
Take
function Div1OnClick()
{
Counter.clickCount ++;
}
$('#Div1').click(Div1OnClick);
versus
$('#Div1').click(function(){ Counter.clickCount++; });
You don't create a new function name in the "above" namespace just to use it once. The actual activity is right there where it's used - you don't need to chase it across the code to where it was written. You can use the actual function as a constant instead of first defining and naming it and then calling it by name, and while there are countless caveats, advantages and tricks connected to closures, that's the one property that sells them.
In general, the main use of closures is to create a function that captures the state from it's context. Consider that the function has the captured variables but they are not passed as parameters.
So, you can think of it of a way to create families of functions. For example if you need a series of function that only differ in one value, but you cannot pass that value as a parameter, you can create them with closures.
The Mozilla Developer Network has a good introduction to closures. It shows the following example:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
}
displayName();
}
init();
In this case the function displayName has captured the variable name. As it stand this example is not very useful, but you can consider the case where you return the function:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Here the function makeFunc return the function displayName that has captured the variable name. Now that function can be called outside by assigning it to the variable myFunc.
To continue with this example consider now if the captured variable name were actually a parameter:
function makeFunc(name) {
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc("Mozilla");
myFunc();
Here you can see that makeFunc create a function that shows a message with the text passed as parameter. So it can create a whole family of function that vary only on the value of that variable ("Mozilla" in the example). Using this function we can show the message multiple times.
What is relevant here is that the value that will be shown in the massage has been encapsulated. We are protecting this value in a similar fashion a private field of a class hides a value in other languages.
This allows you to, for example, create a function that counts up:
function makeFunc(value) {
function displayName() {
alert(value);
value++;
}
return displayName;
}
var myFunc = makeFunc(0);
myFunc();
In this case, each time you call the function that is stored in myFunc you will get the next number, first 0, next 1, 2... and so on.
A more advanced example is the "Counter" "class" also from the Mozilla Developer Network. It demonstrates the module pattern:
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
Here you can see that Counter is an object that has a method increment that advances the privateCounter variable, and the method decrement that decrements it. It is possible to query the value of this variable by calling the method value.
The way this is archived is with an auto-invocation of an anonymous function that creates a hidden scope where the varialbe privateCounter is declared. Now this variable will only be accessible from the functions that capture its value.
Closures are a powerful construct used to implement a lot of additional features in JavaScript. For instance a closure can be used to expose private state as follows:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above example when we call getCounter we create a private variable count. Then we return a function which return count incremented. Hence the function we return is a closure in the sense that it closes over the variable count and allows you to access it even after count goes out of scope.
That's a lot of information stuffed in a few lines. Let's break it down?
Okay, so variables have a lifetime just like people do. They are born, they live and they die. The beginning scope marks the birth of a variable and the end of a scope marks the death of a variable.
JavaScript only has function scopes. Hence when you declare a variable inside a function it's hoisted to the beginning of the function (where it's born).
When you try to access a variable which is not declared you get a ReferenceError. However when you try to access a variable which is declared later on you get undefined. This is because declarations in JavaScript are hoisted.
function undeclared_variable() {
alert(x);
}
undeclared_variable();
When you try to access an undeclared variable you get a ReferenceError.
function undefined_variable() {
alert(x);
var x = "Hello World!";
}
undefined_variable();
When you try to access a variable which is declared later in the function you get undefined because only the declaration is hoisted. The definition comes later.
Coming back to scopes a variable dies when it goes out of scope (usually when the function within which the variable is declared ends).
For example the following program will give a ReferenceError because x is not declared in the global scope.
function helloworld() {
var x = "Hello World!";
}
helloworld();
alert(x);
Closures are interesting because they allow you to access a variable even when the function within which variable is declared ends. For example:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above program the variable count is defined in the function getCounter. Hence when a call to getCounter ends the variable count should die as well.
However it doesn't. This is because getCounter returns a function which accesses count. Hence as long as that function (counter) is alive the variable count will stay alive too.
In this case the function which is returned (counter) is called a closure because it closes over the variable count which is called the upvalue of counter.
Uses
Enough with the explanation. Why do we need closures anyway?
As I already mentioned before the main use of closures is to expose private state as is the case with the getCounter function.
Another common use case of closures is partial application. For instance:
function applyRight(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var rest = Array.prototype.slice.call(arguments);
return func.apply(this, rest.concat(args));
};
}
function subtract(a, b) {
return a - b;
}
var decrement = applyRight(subtract, 1);
alert(decrement(1)); // 0
In the above program we had a function called subtract. We used partial application to create another function called decrement from this subtract function.
As you can see the decrement function is actually a closure which closes over the variables func and args.
That's pretty much all you need to know about closures.
It is because of information hiding.
var myModule = (function (){
var privateClass = function (){};
privateClass.prototype = {
help: function (){}
};
var publicClass = function (){
this._helper = new privateClass();
};
publicClass.prototype = {
doSomething: function (){
this._helper.help();
}
};
return {
publicClass: publicClass
};
})();
var instance = new myModule.publicClass();
instance.doSomething();
In javascript you don't have classes with ppp (public, protected, private) properties so you have to use closures to hide the information. On class level that would be very expensive, so the only thing you can do for better code quality to use closure on module level, and use private helper classes in that closure. So closure is for information hiding. It is not cheap, it cost resources (memory, cpu, etc..) so you have to use closures just in the proper places. So never use it on class level for information hiding, because it is too expensive for that.
Another usage to bind methods to instances by using callbacks.
Function.prototype.bind = function (context){
var callback = this;
return function (){
return callback.apply(context, arguments);
};
};
Typical usage of bound function is by asynchronous calls: defer, ajax, event listeners, etc...
var myClass = function (){
this.x = 10;
};
myClass.prototype.displayX = function (){
alert(this.x);
};
var instance = new myClass();
setTimeout(instance.displayX.bind(instance), 1000); //alerts "x" after 1 sec

multiple calls of another JS function inside a function causes an error

Uncomment //fn in the alg() function and run the code and it will no longer return 0
What is causing this error?? can't I call a function multiple times inside another function definition?
<!DOCTYPE html>
<html>
<script>
function factorial(b)
{
factorial=1;
for(b; b > 1; b--)
{
factorial =b*factorial;
}
return factorial;
}
function alg(n, k)
{
fk = factorial(k);
//fn=factorial(n);
return 0;
}
</script>
<body>
<script>
write=alg(5,2);
document.write(write);
</script>
The problem is that the variable factorial, which is clearly supposed to be a local variable inside the factorial() function, is not declared as a local variable. Fix is simply to declare it using the var keyword:
function factorial(b)
{
var factorial=1;
for(b; b > 1; b--)
{
factorial =b*factorial;
}
return factorial;
}
Without the declaration of factorial as a local variable inside the scope of the factorial() function, factorial just references the factorial() function object, which has global scope because it is declared with the syntax function factorial(){...} at the top level of the script.
So when the code inside factorial() changes this factorial reference to point to a number value, the second factorial() call will fail because the global variable factorial now points to a number, not the factorial() function.
Global variables are widely considered to be one of the bad parts of javascript. This is a good example of why!
UPDATE
For clarification, this issue is not confined to strictly global variables - it's just a general issue of function name scope. When a function is declared like function name(){...} that name has scope within the function and its parent. It's just that here, the parent context happens to be the global context.
Just change your variable factorial of "function factorial(b)" to something else like factorial1. Variable name is being conflicted with function name
function factorial(b)
{
factorial1=1;
for(b; b > 1; b--)
{
factorial1 =b*factorial1;
}
return factorial1;
}

Categories

Resources