function f1 () {
console.log('f1')
}
var s = 'f1'
runLocalFunctionByName(s)
Is this possible at all to write runLocalFunctionByName() or just call f1 without typing f1 in the source code, but using a variable holding its name? I mean without modifying f1 into a method, that answer is obvious: just make myobj.f1 = function or declare it globally like f1= function(). I am talking about normal local functions declared with function keyword only, not as vars, global vars or some other object property.
Not without the use of eval, which is evil (when used for this purpose for sure!).
Global functions could be called as attributes of the window object, but if they are in a local/closure scope that's not possible.
If you need to call functions by name, the only proper solution is storing them as attributes on an object, and then using obj[s]() for calling them.
One way of doing this is by using the instantiating a Function object.
var runLocalFunctionByName = function(fName) {
return (new Function('','return '+fName+'();'))();
};
Calling runLocalFunctionByName with a name of a function will now return the output of the named function.
EDIT
In case of local functions, the scope has to be mentioned, so we can modify the code, such that:
var runLocalFunctionByName = function(fName, scope) {
return (new Function('','return '+(scope?scope:'this')+'.'+fName+'();'))();
};
You can't access a local function outside its scope until unless you assign it to a variable having an accessible scope. MDN: A function defined by a function expression inherits the current scope. That is, the function forms a closure. On the other hand, a function defined by a Function constructor does not inherit any scope other than the global scope (which all functions inherit)
Related
I have no idea how to describe my question .
(function(fn){
var able=123;
function tmp(){
fn()
};
tmp();
})(function(){alert(able)});
This snippet throws a Reference Error :able is not defined' .
Would you please explain how javascript get variables to me ?
The scope of the "fn" function is not the same as the "parent" function, you should pass the "able" argument when you call the fn function, and then istantiate it in the fn function itself, like this:
(function(fn){
var able=123;
function tmp(){
fn(able)
};
tmp();
})(function(able){alert(able)});
Functions create lexical closures at the time of their creation. This means that when your alert function is created, the able variable does not exist. Wrapping the execution of fn in a lexical closure that does know about able at a later moment does not affect the already created lexical closure of fn.
If you come up with a question that better explains what you are trying to do, we can propose how to properly use closures to express that idea.
java script support in function local and global scoping.
in this case the "able" is local function scope you can't access outside the function.
If you use var the variable will be declared in the local scope. If u just declare the variable without a var, it will be declared in the global scope
Your code could be rewritten like this using named functions:
var func1 = function(fn) {
var able=123;
function tmp(){
fn()
};
tmp();
}
var func2 = function() {
alert(able)
}
func1(func2);
I believe this way it is clear that the variable 'able' is defined inside 'func1' (more precisely in its local scope) and you are trying to access it inside 'func2' which is outside the scope of 'func1' so it can not "see" into this scope.
More information about scoping in JavaScript can be found here: What is the scope of variables in JavaScript?
First of all, I recognize there are like 100+ threads on method.this vs var method, etc. That is not what I am asking. I know the differences. I am confused of function expressions VS function declarations in the context of creating objects using a constructor.
What I wanted to know is this: How come function declarations never appear in constructors, but function expressions do? Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
I think it is because either it is local (aka private) and thus inaccessible, or when creating objects, if the constructor does not see the function prefixed with 'this', 'var', or 'constructor.prototype', it skips it.
How come function declarations never appear in constructors, but function expressions do?
They do
Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
You must be doing it wrong.
function Thing() {
function go() {
alert('Hello');
}
this.foo = 1;
this.bar = function () {
go();
}
}
var x = new Thing();
x.bar();
I think it is because either it is local (aka private) and thus inaccessible
Function declarations are locally scoped. That doesn't stop you assigning them to a wider scope, to an object property or using them within the scope they are declared within.
How come function declarations never appear in constructors, but function expressions do?
They do. You could easily replace every function expression with an equivalent function declaration.
Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
Because function declaration declare a function in the current scope, just as var declares a variable. See also Javascript: Do I need to put this.var for every variable in an object? for the difference between variables and properties.
if the constructor does not see the function prefixed with 'this', 'var', or 'constructor.prototype', it skips it.
Nope. It's not about "being seen prefixed with". You are writing the code, and the engine doesn't know what it is executing. A function expression by itself is nothing but an expression, it gathers a meaning when you do assign it somewhere. When you assign it to a property of the current instance (this), it becomes a method for example. The same can be done with a function declaration:
function Constructor() {
// creating local identifiers:
var variable = function expression(){ };
function declaration() { };
// exporting properties:
this.method1 = variable;
this.method2 = declaration;
// or without the local variable:
this.method3 = function expression() { };
}
From Javascript-Garden:
Foo.method = function() {
function test() {
//this is set to the global object
}
test();
}
In order to gain access to Foo from within test, it is necessary to create a local variable inside of method that refers to Foo:
Foo.method = function() {
var that = this;
function test(){
//Use that instead of this here
}
test();
}
Could anyone explain this? As far as I understood, this refers to the global object if it's called in the global scope. But here it's called inside of a function, which is inside a method (first example). Why exactly does it refer to the global object, while the second example doesn't?
As far as I understood, this refers to the global object if it's called in the global scope.
No. this will refer to the default object if the function is called without explicit context. The scope is irrelevant. (In strict mode it will refer to undefined instead).
Why exactly does it refer to the global object
We can't tell what it refers to. The value of this is determined by how the function is called, not how it is defined.
Now you have updated the example, we can see that it is called without context, so this (in the inner function) will be the default object, which in a web browser is window (it would be undefined in strict mode).
while the second example doesn't?
In the second example, the inner function doesn't use this (which will have the same value as the previous example).
The second example uses that instead. that is defined in the scope of the outer function and is set to whatever the value of this is when that function is called.
Assuming that function is called as Foo.method() then (outer) this (and hence that) will be Foo because that is the context on which method was called.
this in a function isn't set when you define the function. It's only dynamically defined to the receiver of the function call.
If you call foo.test(), this in test will be foo.
But if you do
var f = foo.test;
f();
then this in f (which is foo.test) will be the external object (window if you're executing it at the root level).
It would be the same with
foo.test.call(window);
The second example uses a closure to place the outer functions variables on the scope chain of the inner function.
Foo.method = function() {
var that = this;
function test(){
//This function has access to the outer variables scope chain.
}
}
I am doing a small work in JavaScript and I want to avoid problems, so I am asking beforehand.
Can I use two different variables and name them the same in different functions, given that one of these functions calls the other?
So, when I define the variable in the second function, will it interpret as two different variables, or will it rewrite the value of the original variable from the first function? (Or, will it throw an error due to the fact that a variable with that name already exists?)
Here is an example:
function first()
{
var a = somevalue;
second();
}
function second()
{
var a = differentvalue;
}
Thanks!
Variables declared inside a function are local to that function, and doesn't conflict with variables with the same name anywhere else.
You can even have a global variable with the same name, and the code inside the function will only see the local variable.
Example:
var a; // global variable
function first() {
var a; // local variable in first
second();
}
function second() {
var a; // local variable in second
}
(Global variables should of course be used as little as possible, but it's good to know that you can have a local variable that is unaffected by any global variables that may exist.)
A local variable inside a function is not only local to the function, it's actually local to that execution of the function. If you call the function again, a new variable is created, and if the function calls itself (recursion), each level will have it's own variable.
Yes you can, as long as you don't forget the var keyword : the scope of a variable is either the function in which it is declared or the global scope. There is no way from outside the functions to gain access to the variables they declare.
I read about JavaScript closures and I thought that I understood it, but apparently I didn't.
The success function is called when request is succeeded. This means that when the closure (function () {
return obj;
})(); is executed the scope, inside success function, is NOT function (evt) {...} anymore, so how it can still access obj?
How the closure work in this example
EDITED(there is var before obj)
function (evt) {
var obj = evt.data.obj,
$.ajax({
type: "POST",
url: url,
data: data,
success: function () {
var o = (function () {
return obj;
})();
}
});
}
In JS, scope is limited by function.
Everything inside a function to which a variable is scoped can access that variable — including other functions — unless there is another variable of the same name in a narrower scope.
That said, in this example there is no var keyword to localise the scope of the obj anyway, so it is a global. Removed after edit of question
One way to look at it is that closures have access to all scopes above themselves.
Another way would be to say that obj actually is accessible in scope of function function(evt), which is parent to the scope of function(), and therefore, obj is also accessible from function().
Either way, this is how JavaScript works: closure has access to everything that is accessible at the closure's point of definition.
A closure has access to all higher scopes, not only the "parent scope".
Since an obj variable isn't defined in the current scope, JavaScript goes up all the scopes the function has access to until it finds it.
It's like someone looking up a very weird ladder; one which can split to sub-ladders, but when you climb down these sub-ladders, you are still in the bigger ladder.
A closure has by design access to surrounding scope upon creation as it is created within the scope.
Any variables you access in the outer scope is accessed through a reference that will keep the variable alive after the scope within which it was created is destroyed.
That way when the closure executes, the variables it was referencing will still exist and only after the closure is disposed will the variables be released.
Each Function object has an Activation object that represents it's execution context.
Within a group of nested functions, A scope chain is formed starting from the inner most Activation object and ending with the Global object (Global Scope).
So unless there's a name clash between variables ,Each function has access to all of it's parent functions' local variables and parameters in addition to global variables.
Here's a lengthy but very useful explanation.