is a javascript function inside of a function globally scoped? - javascript

Here is an example of the test that I did:
function f1(var1){
alert('f1 called');
function f2(var2){
alert('f2 called');
}
this.data='something else';
this.f2 = f2;
}
f1.data='something';
f1.f3 = function(var3){
alert('f3 called');
}
console.log(f1); //shows the function
console.log(f1.data); //can have properties attached - cool
console.log(f1.f2(2)); //error: "f1.f2" is not a function
console.log(f1.f3(3)); //this works as expected
It appears that the function f2 inside f1 is local in scope. is there any equivalent way to call a function inside a function like this?

Unfortunately, this is bound to the global scope of window because you haven't instantiated an instance of f1 using new f1();
var f = new f1();
f.f2(); // Now works

Depending on what you are trying to achieve, there are a couple of patterns you can use to access the f2 function outside of f1. You can instantiate an f1 object using new:
function f1() {
this.f2 = function () { console.log('f2'); }
}
new f1().f2() //logs 'f2'
Or you can return the function f2 from the function f1:
function f1() {
return function f2() { console.log('f2'); }
}
f1()() //logs 'f2'

change code to:
function f1 (var1){
alert('f1 called');
};
f1.data='something else';
f1.f2 = function f2(var2){
alert('f2 called');
};

Related

Double nesting a function-valued return stops from entering the double nested function

Trying to understand the scope chain and execution context stack articles from David Shariff's Blog, I've tried to understand closures here
function foo() {
var a = 'private variable';
return function bar() {
alert(a);
}
}
var callAlert = foo();
callAlert(); // private variable
I just wanted to test if inner function has the variable object just from its parent or from the whole scope chain, so I added a nested function repeating the example:
function foo() {
var a = 'private variable';
return function bar() {
return function foobar() {
console.log(a);
};
};
}
var callAlert = foo();
callAlert(); //
And that is not giving any result. It seems the interpreter is not even entering the foobar() function. And the syntax is the same than its parent.
But it works if I divide the function declaration and execution.
function foo() {
var a = 'private variable';
return function bar() {
function ra() {
console.log(a);
};
return ra();
};
}
var callAlert = foo();
callAlert(); // private variable
And really I'm trying to guess why; where's the difference from bar() and foobar() functions.
PS - I'm testing on JSFiddle
function foo() {
var a = 'private variable';
return function bar() {
return function foobar() {
console.log(a);
};
};
}
Here you're returning a function that returns a function, so you need to call that new, doubly nested function
var callAlert = foo()();
DEMO
Or any variation on that theme
var getBar = foo();
var getFooBar = getBar();
getFooBar(); //private variable.
Updated demo
The second example works fine because you're still returning one function—a function that simple calls another function.
return function bar() {
function ra() {
console.log(a);
};
return ra();
};

Local and global scope of variables in JavaScript

I have tried reading other posts on the subject but no luck yet. In this code below why doesnt f2() have access to the var defined in f1(). Is not the var "name" a global to the function f2()? Should not f2() see the var "name"?
function f1() {
var name = "david";
function f2() {
document.writeln(name);
}
document.writeln(name);
}
f2(); // does not write out "david".
your f2() is only defined inside f1() scope. you can't call it globally
Javascript is function level scoped, not block scoped. A function has access to it's parent's function variables but not to variables defined in functions within it. You could return f2 from f1 and call it that way
function f1() {
var name = "david";
document.writeln(name);
return f2
function f2() {
document.writeln(name);
}
}
var f2 = f1();
f2();
You need to read up on Javascript Closures.
Here is a version of your snippet which demonstrates how you can access variables from outer function in an inner function (if you want to call inner function globally).
function f1()
{
var name = "david";
return function()
{
console.log(name);
}
}
var f2 = f1();
f2();

JavaScript Internals 101: Hoisting variables and functions

Consider the following examples:
var company = 'Apple',
log = console.log;
function f1() {
log(company);
var company = 'Twilio';
log(company)
}
function f2() {
log(company());
function company() {
return 'Zynga';
}
}
function f3() {
log(company());
var company = function() { return 'RIM'; };
}
log(company);
log('---');
f1();
log('---');
f2();
log('---');
f3();
The output from firebug is:
"Apple"
---
undefined
"Twilio"
---
"Zynga"
---
TypeError: company is not a function
So why is hoisting in f3 giving me the error while others are working just fine?
Let's rewrite your f3 function to show what it would look like after variable hoisting:
function f3() {
log(company());
var company = function() { return 'RIM'; };
}
becomes:
function f3() {
var company; // declaration hoisted
log(company());
company = function() { return 'RIM'; };
}
Now you can see that you are attempting to execute an undefined variable, not a function (hence the "not a function" error).
Note that this is difference from the output of f2 because function declarations are hoisted as a unit.
The variable is hoisted, but setting it is not.
The value of company in f3 is not set until after log(company()) is called. You can see the same behavior in f1.

function expression vs function declaration with regard to javascript 'classes'

When does it make sense to use function expressions instead of function declarations when implementing "private methods"? In both cases, the functions are encapsulated, the only practical difference appears to be that I wouldn't be able to call myFunc1 in the constructor. I know I should be using the prototype property either way, but I'm just curious.
function myClass
{
myFunc1() //error
myFunc2() //success
var myFunc1 = function()
{
}
function myFunc2()
{
}
}
You can call the function assigned to a variable, but you have to assign it before you can call it:
function myClass() {
var myFunc1 = function() {
}
myFunc1() //success
myFunc2() //success
function myFunc2() {
}
}
Those functions are local to the constructor, so it's not the same as using the prototype. To make a public function you need to assign it to the object:
function myClass() {
this.myPublicFunc1 = function() {
}
this.myPublicFunc2 = myFunc2;
function myFunc2() {
}
}
var o = new myClass();
o.myPublicFunc1() //success
o.myPublicFunc2() //success
You must use an expression if you want to invoke the function immediately.
This one invokes it and assigns the return value to the variable:
function myClass {
var myVar = function() {
return 'some value'; // <--- 2. assign the return value to the variable
}(); // <--- 1. invoke the function immediately
function myFunc2() {
}
}
This one invokes it, but assigns the function itself to the variable:
function myClass {
var myFunc1;
(myFunc1 = function() { // <--- 1. assign the function to the variable
// Do something
})(); // <--- 2. invoke the function immediately
function myFunc2() {
}
}

javascript anonymous function scope

I have the following anonymous function:
(function() {
var a = 1;
var b = 2;
function f1() {
}
function f2() {
}
// this => window object!
// externalFunction(this);
})();
function externalFunction(pointer) {
// pointer.f1(); => fail!
}
I need to call external function from this anonymous function and pass it's pointer to call functions f1 & f2.
But I can't do this, as this refer to window object instead of internal scope.
I can set function as:
this.f1 = function() {}
but it's bad idea, as they'll be in global space...
How I can pass anonymous space to external function?
I still wonder why you would make functions to be private, that are needed outside...
But there you go:
(function() {
var a = 1;
var b = 2;
var obj = {
f1: function() {
},
f2: function() {
}
}
externalFunction(obj);
})();
function externalFunction(pointer) {
pointer.f1(); // win
}
Or you can pass f1 and f2 individually, then you don't need to put them into an object.
You can't pass the scope as an object, but you can create an object with whatever you want from the scope:
externalFunction({ f1: f1, f2: f2 });

Categories

Resources