How to call function which inside jQuery scope from globle scope? [duplicate] - javascript

This question already has answers here:
What is the scope of variables in JavaScript?
(27 answers)
Closed 8 years ago.
Here is the jsfiddle.
Code:
$(function(){
f1();//OK
f2();//OK
function f1(){
console.log("1");
}
});
function f2(){
console.log("2");
}
f2();//OK
f1();//NO!!!
As you can see, the f1() is not executed from globe scope(or outside jquery scope). Could some one tell me why?

Functions declared within other functions are ONLY available within the function in which they are declared. They are like local variables in that regard. They are private to the scope in which they are declared and there is no way to access them from the outside.
If you want it available in a higher scope, then declare the function in the higher scope or assign it to a higher scope and then you can call it from both places.
$(function(){
f1();//OK
f2();//OK
});
function f1(){
console.log("1");
}
function f2(){
console.log("2");
}
f2();//OK
f1();//OK
It's also possible to do this (manually assigning a function into the global scope):
$(function(){
// assign function into the top level scope
window.f1 = function(){
console.log("1");
}
f1();//OK
f2();//OK
});
function f2(){
console.log("2");
}
f2();//OK
f1();//OK - only after document is ready and window.f1 has been assigned

This is so-called closure!
JS function has its own scope: variables defined inside a function cannot be visited outside it. If you want to do so, you must have a reference to it from the outer scope.
var globarF1;
$(function(){
f1();//OK
f2();//OK
function f1(){
console.log("1");
}
globarF1 = f1;
});
globarF1();// now it's ok
Here's a more interesting example:
function outer() {
var asdf = 1;
return function() {
return asdf;
}
}
asdf; // Error: asdf is not defined
var qwer = outer();
qwer(); // 1
Notice that outer() just returns an amounymous function, qwer() actually executes the amounymous function, and this is the power of closure: function outer's execution scope is not destroyed even if it has returned, because there is a reference to its local variable from outside, and you can visit the variable asdf inside it in this way.

Related

JavaScript: how are functions and their scopes/lexical environments passed around?

I'm playing with closure and have no problem understanding how inner functions have access to outer lexical environments:
function outer() {
var bar = 0;
function inner() {
console.log(bar);
}
inner();
}
outer(); // prints '0'
But what gets me is this:
function foo() {
return function inner() {
console.log(bar);
}
}
function outer() {
var bar = 0;
var fakeInner= foo(); // not the same as "var fakeInner= function () { console.log(bar); }"
fakeInner();
}
outer(); // ReferenceError: bar is not defined
Here I try to "define" an "inner function" fakeInner by assigning it to a function expression returned from an outside function.
I used to think that JavaScript creates the fakeInner inside with a "copy" of its code, something like: var fakeInner= function () { console.log(bar); }, which would then have access to bar, but this is not the case -- it appears when fakeInner is invoked, JavaScript traces back to its definition. Am I understanding this correctly? That is, function objects (either declarations or expressions) are mere references to their definition spots, and passing them do not change their lexical environments (hence inner functions have to be defined inside with explicit syntax)?
Yes, functions do only have access to their own lexical environment - from where they were defined. JavaScript does not have dynamic scope where a function has any kind of access to the scope where it is called.
This happens by attaching the scope to the function object, it is a part of the closure.
In this example,
function outer() {
var bar = 0;
function inner() {
console.log(bar);
}
inner();
}
outer();
scope of bar is outer function and will be available for all function defined in it.
function foo() {
return function inner() {
console.log(bar);
}
}
function outer() {
var bar = 0;
var fakeInner = foo(); // not the same as "var fakeInner= function () { console.log(bar); }"
fakeInner();
}
outer();
In this example, again bar is accessible inside outer but foo is outside it. Hence reference error is thrown.
Also refer What is the scope of variables in JavaScript? for more information.
The scope of inner functions is its own outer function. Not the function it is being called from.

Why is the function returned from a callback function not forming closure over the function where it is called?

I am having trouble in understanding the output from the below code (In Javascript) :
function outerFunction(callback){
var x =10;
var myCallbackRet = callback();
myCallbackRet();
}
outerFunction(function(){
return function(){
console.log(x); //output - x is not defined
}
});
As far as i understand when function myCallbackRet is called then [[Scope]] property of myCallbackRet is set to the Scope chain of the outerFunction and so the variable x should be accessible inside `myCallbackRet'.
Why is the output 'undefined'? Thanks a lot in advance.
Basically it has to do with where your function is defined. It was defined out of scope. Closure only works when a function is defined some where. Setting a variable to a function and calling it doesn't make everything above it available inside the function being called or there would be no reason to pass parameters to a function. Something like this would work.
function outerFunction(callback){
var x =10;
var myCallbackRet = callback();
myCallbackRet(x);
}
outerFunction(function(){
return function(y){
console.log(y);
}
});
Or this:
function outerFunction(callback){
var myCallbackRet = callback();
myCallbackRet();
}
outerFunction(function(){
var x =10;
return function(){
console.log(x);
}
});
Your anonymous function
function(){
return function(){
console.log(x)
is defined on the same scope (global) as outerFunction, but x is defined inside the scope outerFunction.
The scope of the function is set at the moment the function is defined, rather than at the moment when a function is assigned to variable.

Output of below code statements

var abc = function() {
console.log(1);
}
function abc() {
console.log(2);
}
abc();
I am expecting that it will console 2, but no it will console 1 because of
function and variable hoisting.Anybody who want to make it more clear.
In JavaScript, a name enters a scope in one of four basic ways and the order of hoisting follows following order...
Language-defined: All scopes are, by default, given the names this and arguments
Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function
Function declarations: These are of the form function foo() {}
Variable declarations: These take the form var foo;
Reference: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
In your case the 1st function is type 4 and the second function is type 3. Therefore the second function is hoisted first assigning the function reference to abc. And then the first function is hoisted reassigning the reference to abc. Your code is compiled in following order,
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
}
abc();
Note that only declarations are hoisted. Assignments are not hoisted.
var bar = 'test';
var foo = function(){/*foo 1*/};
var foo;
function foo(){/*foo 2*/}
alert(foo);
will be complied in this order,
function foo(){/*foo 2*/} //function declaration
var bar; //variable declaration
var foo; //variable declaration
bar = 'test';
foo = function(){/*foo 1*/};
alert(foo);
var hoisting
the Key to understanding how scope in JavaScript works is understanding the concept of hoisting.
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declared. This
behavior is called "hoisting", as it appears that the variable
declaration is moved to the top of the function or global code.
console.log("function hoisting:::: ",abc()); /* log = 2 we are calling the function(hoisting)*/
var abc = function() {
console.log(1);
};
console.log("var:::: ",abc()); /* log = 1*/
function abc() {
console.log(2);
}
abc(); /* log = 1*/
console.log("function:::: ",abc()); /* log = 1*/
So in your case you are not calling the function, to call the function log it on the top.
this is how the javascript engine interprets it
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
};
abc();
REF: JavaScript Scoping and Hoisting
If you're simply asking why the function abc isn't the one being executed despite it being declared most recently, it's because, In Javascript, functions are hoisted to the top of the current scope.
That means your code is morphed into something like the following:
function abc() { console.log(2); }
var abc = function() { console.log(1); }
abc();
That means, when it comes time to call abc, the "active" one is the one that logs 1.
One of the best articles I ever found on this behaviour was the one over at adequately good.

JavaScript: create a function within a specific scope

JavaScript: I need create a function within a specific scope.
The function to be created, is generated dynamically by a previous process of code generation. And the scope for the definition of this function may also change.
Look this example:
var createFnInOtherScope = function() {
console.debug('createFnInOtherScope: Who I am', this);
//This code can not be modified because it's dynamically generated
function MyFunction() {
console.debug('MyFunction');
}
}
var obInitial = {
createFn: function() {
console.debug('createFn: Who I am', this);
createFnInOtherScope.call(window);
}
}
obInitial.createFn();
//ReferenceError: MyFunction is not defined
window.MyFunction();
How I can do this?
Thanks.
If I understand you correctly, what you're asking is impossible.
Scope in Javascript is a lexical construct, meaning that what's in scope is defined by its physical location (at parse time) in the source file with respect to any enclosing functions.
You can't retrospectively add something into a scope once that scope has (lexically) been closed off.
Function scope is defined at parse time. You can create a function and make it visible as a window property:
function outer() {
function inner() {
console.log("hello world");
}
window.inner = inner;
}
window.inner(); // hello world
But that does not alter the scope of the "inner" function. It's visible and callable via the global object, but the function is unalterably in the scope of that "outer" function.
Just define this function in this context:
var createFnInOtherScope = function() {
this.MyFunction = function() {
console.debug('MyFunction');
};
};
DEMO: http://jsfiddle.net/Ur6vF/

Move JavaScript methods into global scope

In JavaScript, is it possible to move inner functions from one function into the global scope? I haven't yet found any straightforward way to do this.
function moveMethodsIntoGlobalScope(functionName){
//move all of functionName's methods into the global scope
//methodsToPutIntoGlobalScope should be used as the input for this function.
}
//I want all of the methods in this function to be moved into the global scope so that they can be called outside this function.
function methodsToPutInGlobalScope(){
function alertSomething(){
alert("This should be moved into the global scope, so that it can be called from outside the function that encloses it.");
}
function alertSomethingElse(){
alert("This should also be moved into the global scope.");
}
}
If you don't want to make changes in methodsToPutInGLobalSpace you can use the following dirty hack:
var parts = methodsToPutInGlobalScope.toString().split('\n');
eval(parts.splice(1, parts.length - 2).join(''));
As final solution we can use:
moveMethodsIntoGlobalScope(methodsToPutInGlobalScope);
alertSomething(); //why doesn't this work?
function moveMethodsIntoGlobalScope(functionName){
var parts = functionName.toString().split('\n');
eval.call(window, parts.splice(1, parts.length - 2).join(''));
}
//I want all of the methods in this function to be moved into the global scope so that they can be called outside this function.
function methodsToPutInGlobalScope(){
function alertSomething(){
alert("This should be moved into the global scope, so that it can be called from outside the function that encloses it.");
}
function alertSomethingElse(){
alert("This should also be moved into the global scope.");
}
}
Live demo
Not very sophisticated, but would work.
function copyInto(arr, context) {
//move all of functionName's methods into the global scope
//methodsToPutIntoGlobalScope should be used as the input for this function.
for (var i = 0; i < arr.length; i += 2) {
var exportName = arr[i];
var value = arr[i + 1];
eval(exportName + "=" + value.toString());
}
}
//I want all of the methods in this function to be moved into the global scope so that they can be called outside this function.
function methodsToPutInGlobalScope() {
function alertSomething() {
alert("This should be moved into the global scope, so that it can be called from outside the function that encloses it.");
}
function alertSomethingElse() {
alert("This should also be moved into the global scope.");
}
copyInto(["alertSomething", alertSomething, "alertSomethingElse", alertSomethingElse], window);
}
methodsToPutInGlobalScope();
alertSomething();
alertSomethingElse();
Yes, this is possible. If you declare a variable using var keyword that variable becomes local only, but if you don't it becomes a global one.
function foo(){
var test = 'test'; // <- Using var keyword
}
foo(); // <- execute the function
console.log(test); // undefined
But if we do the same thing without var keyword:
function foo(){
test = 'test'; // <- Using var keyword
}
foo(); // <- execute the function
console.log(test); // test
In order to make your inner functions global, you'd declare anonymous functions without var keyword
function methodsToPutInGlobalScope() {
alertSomething = function () {
alert("This should be moved into the global scope, so that it can be called from outside the function that encloses it.");
}
alertSomethingElse = function () {
alert("This should also be moved into the global scope.");
}
}
methodsToPutInGlobalScope(); // <- Don't forget to execute this function
alertSomething(); // Works
alertSomethingElse(); // Works as well

Categories