How does closure works in the below function - javascript

I am new to closure concept. Can somebody explain me how closure works in the below function.
As per my understanding, function b() can access 'var y' if it is defined within A() and not under function a(). But it accesses the variable value though it is within another function.
function A(){
function a(){
var y = 'some text!!';
return function(x){
console.log(y);
}
}
function b(someVar){
var buffElem = [];
someVar(buffElem);
}
var myFun = a();
var mySecFun = b(myFun);
} A();
As per the above function,
myFun = function (x){
console.log(y);
}
How does myFun understands what is y?

Related

Advantages of using inner functions(javascript)

this might not be a very specific question but I was wondering what are the advantages of using an inner function? I've recently started reading on closures (javascript) and they always refer to inner functions.
var pet = function(name) {
var getName = function() {
return name;
}
return getName;
}
myPet = pet('Vivie');
myPet();
Why would we not want to seperate the getName function and introduce a 'name' parameter so that we could call it independantly?
var pet = function(name){
return getName();
}
function getName(name){
return name;
}
Thank you, I am quite new to javascript
Try this article. Simple guide to understand closure in JavaScript
I copied here a part of the code explained in the article.
Run this code snippet to see the behavior of the inner function.
<script>
function outer() {
var b = 10;
var c = 100;
function inner() {
var a = 20;
console.log("a= " + a + " b= " + b);
a++;
b++;
}
return inner;
}
var X = outer(); // outer() invoked the first time
var Y = outer(); // outer() invoked the second time
//end of outer() function executions
X(); // X() invoked the first time
X(); // X() invoked the second time
X(); // X() invoked the third time
Y(); // Y() invoked the first time
</script>

Javascript function scope and parameter

Here is the code:
function b() {
console.log(x);
};
function a() {
var x= 1;
b();
}
a();
//the output is : x is not defined!
Can anybody help explain why it will ouput undefined? I thought it would output 1. Why function b() can't get the variable x?
You're confusing closures with actual invoking of a function. If you had function b inside function a, then you can access x like so.
function a() {
var x= 1;
function b() {
console.log(x); // print out 1
};
b();
}
You must pass x variable as parameter:
function b(x) {
console.log(x);
};
function a() {
var x= 1;
b(x);
}
a();
If a var is define inside a function, the var can only be use within the function. If a var is define outside the function, then it can be use anywhere. Your var x =1 is defined inside function a(), so it can only be use inside function a(). To solve your code, you can simply move var x= 1 outside function a(). Here's the code:
function b() {
console.log(x);
}
var x= 1;
function a() {
b();
}
Or, I could suggest you use this instead. It's much shorter:
var x= 1
function b() {
console.log(x);
}

How do i pass my scope correctly to look for variables

i was trying to use the javascript APPLY function to pass scope from 1 function to another, but it seems that i might be doing it wrong?
Here is a fiddle if you need it: http://jsfiddle.net/C8APz/
Here is my code:
function a(){
var x = "hello";
b.apply(this, []);
}
function b(){
console.log("x: ", x);
}
a();
i was thinking that while the scope is passed, the variables / variable reference are not.
Is there a way to do something like this without defining Globals?
Should i add the data to the actual part of it, such as this.x = x;? and then in the other function just fetch it? var x = this.x;
function a(){
var x = "hello";
this.x = x;
b.apply(this, []);
}
function b(){
var x = this.x;
console.log("x: ", x);
}
a();
Edit: It seems that the second example assigns in the global scope, which isnt good, and with the scope, i was attempting to pass an understanding of context to. It seems that you really have to define a context before you pass it, otherwise, for the most part this refers to window
You cannot pass scope around.
You can either move the function declaration for b inside the function declaration for a so that the scope is right to start with, or you can pass the variables you care about using arguments.
function a(){
var x = "hello";
b();
function b(){
console.log("x: ", x);
}
}
a();
function a(){
var x = "hello";
b(x);
}
function b(x){
console.log("x: ", x);
}
a();
Declare var x; out of the function body...
var x;
function a(){
x = "hello";
b.apply(this, []);
}
function b(){
//a.apply(this,[]);
console.log("x: ", x);
}
a();

Javascript: got 'undefined' when using 'this' to access outer scope variable in 'private' child function

I have a habit of setting all my variables to its parent scope, instead of calling them implicitly:
function outer() {
var x, y;
function inner() {
var x = this.x;
x = ...// doing stuff here
y = ....// implicit calling parent variable
}
}
so that if I mistype my variable, it won't go to global space. But it seems like declare variable with this within private function will return me undefined:
function f() {
var x = [0];
function f1() {
console.log('f1:', this.x, x);
f2();
}
function f2() {
console.log('f2:', this.x, x);
}
return { x:x , f1:f1 };
}
var foo = f();
foo.f1();
//output
f1: [0] [0]
f2: undefined [0]
If I understand it correctly, it shouldn't happen, as both f1 and f2 should have access to its outer scope by using this. Is there any concept I am missing here? Or is it something I just have to live with for now?
Update: To clarify, my main concern is why there is the difference between f1 and f2. I prefer to keep f2 hidden because it will do some internal works, and other developers should not use it when they declare something from f().
Also try this:
function f() {
var x = [0];
function f1() {
console.log('f1:', this.x, x);
f2.call(this);
}
function f2() {
console.log('f2:', this.x, x);
}
return { x:x , f1:f1 };
}
var foo = f();
foo.f1();
This way the context of f2 will be properly set.
In your code this in f2 refers to the window object, because f2 wasn't declared as a method. f1 was declared as a method of the returned object when writing { x:x , f1:f1 }. In f2 x is visible not because it is run in the scope of f() but because f2 gets it as a closure. That means in f2, all variables will be visible that was in the same scope when it was created.
What the this refers to will be set at invocation time. If you run a function as property of an object like foo.f1() it is considered as a method, and this will be set to the object. But when you just invoke a function like f2() the scope will be the same it was invoked in, in your case it is the window object, because foo is a global in the window object.
In f1 this refers to the hidden f(), therefore if you want f2 also be run in that scope you can use f2.call(this). The argument of .call() will be the this of the function when run.
When your f function returns an object, it doesn't have f2 method. f2 method is an inner method of f and exists only in its scope.
If you use this code:
function f() {
var x = [0];
function f1() {
console.log('f1:', this.x, x);
this.f2();
}
function f2() {
console.log('f2:', this.x, x);
}
return { x:x , f1:f1, f2:f2};
}
var foo = f();
foo.f1();
then this in f1 method will have access to the f2 method of this, and object's f2 method will return the correct x.
You returned this from the function:
{ x : x, f1 : f1 }
This sets the the this objects properties to the above. f2 is not apart of the object so it can't access the this that it refers to.

JavaScript pass scope to another function

Is it possible to somehow pass the scope of a function to another?
For example,
function a(){
var x = 5;
var obj = {..};
b(<my-scope>);
}
function b(){
//access x or obj....
}
I would rather access the variables directly, i.e., not using anything like this.a or this.obj, but just use x or obj directly.
The only way to truly get access to function a's private scope is to declare b inside of a so it forms a closure that allows implicit access to a's variables.
Here are some options for you.
Direct Access
Declare b inside of a.
function a() {
var x = 5,
obj = {};
function b(){
// access x or obj...
}
b();
}
a();
If you don't want b inside of a, then you could have them both inside a larger container scope:
function container() {
var x, obj;
function a(){
x = 5;
obj = {..};
b();
}
function b(){
// access x or obj...
}
}
container.a();
These are the only ways you're going to be able to use a's variables directly in b without some extra code to move things around. If you are content with a little bit of "help" and/or indirection, here are a few more ideas.
Indirect Access
You can just pass the variables as parameters, but won't have write access except to properties of objects:
function a() {
var x = 5,
obj = {};
b(x, obj);
}
function b(x, obj){
// access x or obj...
// changing x here won't change x in a, but you can modify properties of obj
}
a();
As a variation on this you could get write access by passing updated values back to a like so:
// in a:
var ret = b(x, obj);
x = ret.x;
obj = ret.obj;
// in b:
return {x : x, obj : obj};
You could pass b an object with getters and setters that can access a's private variables:
function a(){
var x = 5,
obj = {..},
translator = {
getX : function() {return x;},
setX : function(value) {x = value;},
getObj : function() {return obj;},
setObj : function(value) {obj = value;}
};
b(translator);
}
function b(t){
var x = t.getX(),
obj = t.getObj();
// use x or obj...
t.setX(x);
t.setObj(obj);
// or you can just directly modify obj's properties:
obj.key = value;
}
a();
The getters and setters could be public, assigned to the this object of a, but this way they are only accessible if explicitly given out from within a.
And you could put your variables in an object and pass the object around:
function a(){
var v = {
x : 5,
obj : {}
};
b(v);
}
function b(v){
// access v.x or v.obj...
// or set new local x and obj variables to these and use them.
}
a();
As a variation you can construct the object at call time instead:
function a(){
var x = 5,
obj = {};
b({x : x, obj: obj});
}
function b(v){
// access v.x or v.obj...
// or set new local x and obj variables to these and use them.
}
a();
Scope is created by functions, and a scope stays with a function, so the closest thing to what you're asking will be to pass a function out of a() to b(), and that function will continue to have access to the scoped variables from a().
function a(){
var x = 5;
var obj = {..};
b(function() { /* this can access var x and var obj */ });
}
function b( fn ){
fn(); // the function passed still has access to the variables from a()
}
While b() doesn't have direct access to the variables that the function passed does, data types where a reference is passed, like an Object, can be accessed if the function passed returns that object.
function a(){
var x = 5;
var obj = {..};
b(function() { x++; return obj; });
}
function b( fn ){
var obj = fn();
obj.some_prop = 'some value'; // This new property will be updated in the
// same obj referenced in a()
}
what about using bind
function funcA(param) {
var bscoped = funcB.bind(this);
bscoped(param1,param2...)
}
No.
You're accessing the local scope object. The [[Context]].
You cannot publicly access it.
Now since it's node.js you should be able to write a C++ plugin that gives you access to the [[Context]] object. I highly recommend against this as it brings proprietary extensions to the JavaScript language.
You can't "pass the scope"... not that I know of.
You can pass the object that the function is referring to by using apply or call and send the current object (this) as the first parameter instead of just calling the function:
function b(){
alert(this.x);
}
function a(){
this.x = 2;
b.call(this);
}
The only way for a function to access a certain scope is to be declared in that scope.
Kind'a tricky.
That would lead to something like :
function a(){
var x = 1;
function b(){
alert(x);
}
}
But that would kind of defeat the purpose.
As others have said, you cannot pass scope like that. You can however scope variables properly using self executing anonymous functions (or immediately executing if you're pedantic):
(function(){
var x = 5;
var obj = {x:x};
module.a = function(){
module.b();
};
module.b = function(){
alert(obj.x);
};
}());
a();
I think the simplest thing you can do is pass variables from one scope to a function outside that scope. If you pass by reference (like Objects), b has 'access' to it (see obj.someprop in the following):
function a(){
var x = 5;
var obj = {someprop : 1};
b(x, obj);
alert(x); => 5
alert(obj.someprop); //=> 'otherval'
}
function b(aa,obj){
x += 1; //won't affect x in function a, because x is passed by value
obj.someprop = 'otherval'; //change obj in function a, is passed by reference
}
You can really only do this with eval. The following will give function b function a's scope
function a(){
var x = 5;
var obj = {x};
eval('('+b.toString()+'())');
}
function b(){
//access x or obj....
console.log(x);
}
a(); //5
function a(){
this.x = 5;
this.obj = {..};
var self = this;
b(self);
}
function b(scope){
//access x or obj....
}
function a(){
var x = 5;
var obj = {..};
var b = function()
{
document.println(x);
}
b.call();
}
Have you tried something like this:
function a(){
var x = 5;
var obj = {..};
b(this);
}
function b(fnA){
//access x or obj....
fnA.obj = 6;
}
If you can stand function B as a method function A then do this:
function a(){
var x = 5;
var obj = {..};
b(this);
this.b = function (){
// "this" keyword is still === function a
}
}

Categories