How can I execute a function using a variable name? - javascript

Here is my code:
$(function(){
function myfunc(){
alert("executed");
}
var function_name = "myfunc";
window[function_name]();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
As you can see, that function is not defined. Why? And how can I make it working?

The function is not defined in the global scope so it’s not a member of the window object.
You can attach the function to the window object like this.
$(function(){
window.myfunc = function(){
alert("executed");
};
var function_name = "myfunc";
window[function_name]();
})

It works only for global functions, because the scope is identically with the window object.
You could assing a function to a wanted property of the window object, just as to any other object.
function myfunc(){
alert("executed");
}
$(function(){
var function_name = "myfunc";
window[function_name]();
window.foo = _ => console.log('foo');
window.foo();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

While the direct answer to your question is that your function wasn't defined as a Global and so, attempting to call it as a property of window fails, putting your function into Global scope is not really a good answer.
Instead, make the function a method of a user-defined object (that can be put into any scope you like) and call the function as a property of that object:
// Immediately-Invoked Function Expression (IIFE)
// that keeps all of its contents out of the Global scope
(function(){
let functionHolder = {
someFunction : function(){ console.log("You did it!"); }
};
// Set up a variable that has the same name as the function
let funcName = "someFunction";
// Call the function via the object
functionHolder[funcName]();
})()

Related

How to work with setInterval and constructor?

how to work with setInterval and constructor's method.
console.log is showing undefined. Can anyone explain why and how to access the variable of constructor from setInterval.
var aa=new test();
var bb;
window.onload= function(){
bb=setInterval(aa.b,1000);
}
function test(){
this.a=1;
this.b=function (){
console.log(this.a);
}
}
Try wrapping it in a function like this:
setInterval(() => aa.b(), 1000);
The reason your way doesn't work is that you pass the b function to the setInterval, but then it lose it's this reference, so this becomes the global window object, and window.a is undefined.
Wrapping it in a function make the this be aa as you invoking the function on the aa object.
If you don't want to wrap your function in another function, you can also use bind:
setInterval(aa.b.bind(aa), 1000);
Here the this is forced to be aa.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
setInterval(aa.b.bind(aa),1000);
The others are correct - the this refers not to test instance anymore, an easier way to fix (correctly) this is using a new variable:
var aa=new test();
var bb;
window.onload= function(){
bb=setInterval(aa.b,1000);
}
function test(){
var self = this; //keep the right 'this'.
this.a=1;
this.b=function (){
console.log(self.a); //changed, `self` instead of `this`
}
}

not able to execute the named functions that are also refereed

i'm learning about functions. i'm confused in one scenario.
suppose i have three functions
<script>
var fnRef = function() {
console.log("i'm function with no name but refered to fnRef");
};
var funRef2 = function test() {
console.log("im test reffered to funRef2");
};
function test2() {
console.log("i'm test2 named function")
};
</script>
fnRef, fnref2 and test2 will be assigned to window as a property as fnRef and fnRef2 are variable and test2 is named function that act as variable.
but why test2 is not assigned to the global object(window) when refered by funref2? and why i'm not able to execute test(); can someone tell me what is happening in detail.
The named function expression is useful so you can access the function inside it's own scope without using arguments.callee, and it also makes it easier when debugging as the name can be seen in stack traces, breakpoints etc.
This name is then local only to the function bodys scope, meaning
var test1 = function test2() {
if (something) test2(); // available in this scope only
}
test2(); // not here
You can't call the function by it's name, only by the variable it's assigned to, as the functions name is limited to the functions scope when it's a function expression.
When defining a function declaration, the name is assigned to the current scope, and hoisted, so this
var bar = test();
function test() { return 'foo'; }
is more or less turned into this
var test = function() { return 'foo'; }
var bar = test();

Executing another function from other function in javascript

Hey guys am a bit confused in running a function from the other. What I have tried is:
var a = (function() {
var babe = function() {
console.log('yay');
};
})();
When I run the code like a.babe() it gives me error like TypeError: Cannot read property 'babe' of undefined. Why is it happening like this?
I want to call the function babe from a ... How can i do it?
I hope you guys can help me ...
Thanks in advance.
You are creating a function called babe and it stays only within the scope of the immediately invoked function expression (IIFE) surrounding it. And since you are not returning anything to the caller, by default, the function call will be evaluated to undefined and that will be stored in a. That is why you are getting the error,
TypeError: Cannot read property 'babe' of undefined
It means that, you are trying to access a property called babe on an undefined value. In this case, a is undefined.
Instead of all this, you can simply return the babe function from the IIFE, wrapped in an object, like this
var a = (function() {
return {
babe: function() {
console.log('yay');
}
};
})()
Now, that the returned object is assigned to a, you can invoke babe function like this
a.babe();
babe is a local variable to the IIFE in that code. It isn't returned. It isn't a property of anything. It isn't accessible.
You have to expose it publicly if you want it to call it from outside that function.
var a = (function() {
var babe = function() {
console.log('yay');
}
return babe;
})();
a();
var a = (function() {
var babe = function() {
console.log('yay');
}
return {
"babe": babe
};
})();
a.babe();
Why have you made a a self executing function? What you want to do is to make a function babe part of an Object a for that, simply do this:
var a = {
babe: function() {document.write('yay');}
}
a.babe();
I have made an object a and added a function babe inside it.. then used the dot notation to access the function inside object a
To use your code you must do
var a = (function() {
var babe = function() { console.log('yay'); }
return babe
})();
a();
To make it a.babe() look at #thefourtheye or #Quentin.
The dot syntax is used to access a "property" of an object. So, in a simple example, you could use something like:
var a = {
babe: function(){ console.log('yay') }
};
a.babe(); // yay
In the case of your example, if you want to create a closure to hide other variables and functions from the global scope, you have to return an object that will then get assigned to a:
var a = (function() {
return {
babe: function(){ console.log('yay') }
}
})();
a.babe(); // yay
Just remember, anytime you use a dot, the variable in front HAS to be an object.

Declaring Function As Variable

function shortUrl () {
$['post']('http://tinyurl.com/api-create.php?url=http://json-tinyurl.appspot.com/', function (a) {
});
};
I Want to make this function as a var so I can use shortUrl Anywhere in my script. Like
var shortaddress = shortUrl ();
I want to use the result in next function.
function shortUrl () {...}
is equivalent to
var shortUrl = function () {...};
So, it is already a variable.
A function is already a variable, so you can use it as such. For instance:
function foo() {
// ...
};
is more or less the same as
var foo = function() {
// ...
};
Basically, if you drop the parentheses and arguments (foo instead of foo()), you can use any function as a normal variable.
Therefore you can for instance assign it to other variables, like you normally would:
var bar = foo; // note: no parentheses
bar(); // is now the same as foo()
Or you can pass it as an argument to another function:
function callFunc(func) {
func(); // call the variable 'func' as a function
}
callFunc(foo); // pass the foo function to another function
If you want to use the shortUrl function anywhere, it must be declared in global scope. Then that variable becomes a property of Window object. For example the following variables
<script type="text/javascript">
var i = 123;
function showA(){ alert('it'); window.j = 456; }
var showB = function() { alert('works'); var k = 789; this.L = 10; }
</script>
are declared directly in Window object and so become its attributes. Thus now they can be easily accessed from any script. For example all the following commands work:
<script type="text/javascript">
alert(i); alert(window.i);
showA(); window.showA();
showB(); window.showB();
alert(j); alert(window.j);
alert(new showB().L); // here the function was called as constructor to create a new object
</script>
Functions in javascript are objects and so they can hold attributes in themselves.
In the example above you can consider the k variable to be a private property and the L variable a public property of the showB object(or function). And another example: if you include jQuery library in your page, jQuery usually exposes itself as window.jQuery or window.$ object. Just it's generally recommended to use global variables very sparely and carefuly to prevent possible conflicts.

Why the property of this cannot be accessed directlly within a private function in a closure?

In my own answer for A JavaScript VM that interprets code written in JSON I stated that the "public" properties of a JavaScript closure cannot be accessed in a "private" function.
The example given in that post is
function anobject(){
var privatefunction = function(){
//publicfunction(); //wrong; you have no access to it
console.log(this); //refer to the global object, not the object creating
};
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
I think the reason is for some backward compatibility issues privatefunction must belong to the global object. So the public function is only an anonymous function that assigned to a property of this. This explains why calling publicfunction will fail because it need to have a reference to this first.
However, the following fix is still not work:
function anobject(){
var privatefunction = function(){
//publicfunction(); //wrong; you have no access to it
console.log(this); //refer to the object creating
}.bind(this);
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
As I explicitly specify that privatefunction should be bound with the object creating, calling publicfunction should work but it does not. I have to do the following:
function anobject(){
var privatefunction = function(){
this.publicfunction();
console.log(this); //refer to the object creating
}.bind(this);
this.publicfunction = function(){
console.log(this); //refer to the object creating
}
}
Another workaround (the way that I am using) is the following:
function anobject(){
var privatefunction = function(){
publicfunction();
console.log(this); //refer to the object creating
};
var publicfunction = function(){
console.log(this); //refer to the object creating
}
this.publicfunction = publicfunction;
}
Now is the question part. What is the reason behind this behavior? What is it trying to avoid by disabling access this's properties without explicit specification?
UPDATE: the main part of the question is : When the interpreter cannot find a name in the scope chains, why should'nt it have a look at the this properties?
The problem here is that the reference this is determined by the caller of the function/method, for example:
function anobject(){
// here "this" is the object
var privatefunction = function(){
// here "this" is the object **that called privatefunction()**
};
this.publicfunction = function(){
// this method will always be called by the object, so "this" is the object
}
}
To achieve what you want you could also try this:
function anobject(){
var that = this;
var privatefunction = function(){
[do what you like using "that"]
};
this.publicfunction = function(){
[here you can use "this" directly, or "that"]
}
}
See also how javascript scope works, here What is the scope of variables in JavaScript? and on the web.
In the second example, publicfunction() is delcared as a property of the object this:
this.publicfunction = function(){
console.log(this);
}
Therefore, this function is not directly accessible by its name publicfunction(), and that is independent of the context. The function does not actually belong to any context, but rather to the object of which it is a property.
In your example, when privatefunction() calls publicfunction(), this raises an error because there is no function declared as a variable with the name publicfunction(), and not because this's properties are not accessible:
function anobject(){
var privatefunction = function(){
//publicfunction(); // You cannot call publicfunction() because there is
// no function defined with this name
}.bind(this);
this.publicfunction = function(){
console.log(this);
}
}
Look at this example, publicfunction() is not accessible even within anobject():
function anobject(){
this.publicfunction = function() {
console.log(this);
}
// publicfunction(); // Wrong because publicfunction()
// was not defined as a variable
}
However, if publicfunction() was defined as a variable within the context of anobject(), then this function would be accessible by its name. For example you can simply declare function publicfunction() within the closure of anobject():
function anobject(){
function publicfunction() {
console.log(this);
}
publicfunction(); // You can access publicfunction() here
}
But in this case, publicfunction() is not accessible outside the execution context of anobject(), therefore it can be regarded as a 'private' function:
var a = new anobject();
if(typeof a.publicfunction === 'undefined')
console.log('Public function is undefined outside of anobject()');
As a result, that's why we use the this keyword to declare publicfunction(): it makes it accessible outside the context of anobject(), but doing so define this function only as a property of anobject().
Therefore the only way to access this function is by calling this.publicfunction():
function anobject(){
var privatefunction = function(){
this.publicfunction();
console.log(this);
}.bind(this);
this.publicfunction = function(){
console.log(this);
}
}
More details regarding the this keyword: How does "this" keyword work within a function?
Variable vs. Properties in JavaScript: http://javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/

Categories