How to access function inside of function? - javascript

today my question is asking how I would access a function inside a function. So, for example, I have a button, and if I click it, it would alert. The thing is, if you have a function surrounding the function, the inside function with the alert would not alert.
Here's an example:
html:
<button onclick="doStuff()">Alert</button>
js:
function nothing() {
var doStuff = function() {
alert("This worked!")
}
}
so the doStuff() function would not work. Can someone help me find a way to access it?

#Joseph the Dreamer is ultimately correct, but if you were dead set on calling a function that's nested in another function you could use an OOP approach.
Create a javascript "class" object and scope your function to "this":
function Nothing() {
this.doStuff = function() {
alert("works");
}
}
Next you add an id to your button,
along with a click event listener
Then, inside your click event you can call doStuff within the Nothing "Class" function like this:
var object = new Nothing();
object.doStuff();
https://jsfiddle.net/me7fek5f/

You can't. That's because it's enclosed in a scope that you can't really access globally. The only way you can access it is to expose it somewhere outside nothing.

Is this a homework question?
You're probably asked to do something like this:
function nothing() {
var doStuff = function() {
alert("This worked!")
}
var yourButton = getYourButton();
attachClickListener(yourButton, doStuff);
The implementations of getYourButton and attachClickListener are left to the reader.

Related

how to change function definition captured in closure

This is another Javascript closure question. I run the following code as soon as the document loads:
var handlers = (function () {
var clickHandler = function() { alert ('click!'); }
return {
clickHandler : clickHandler
}
}());
$('#element').addEventListener('click', handlers.clickHandler);
Then at some later point I want to replace the functionality of the handler and thus do something like:
handlers.clickHandler = function() { alert ('changed handler!'); }
From my understand of Javascript closures the event listener should keep a reference of the clickHandler function, and thus the functionality should change accordingly. Yet, this is not what happens. The event listener triggers the initial function. I have managed to achieve the result I want using eval but this feels like a hack. Is there a legitimate way to do what I want?
$('#element').on('click', /*the solution: */ () => handlers.clickHandler());
You need to resolve the identifier on execution of the handler, not on registration. That can be done by wrapping the call into a function, like i did above ( with an arrow function).

Shorthand to call function from scope

If I have a function as follows (pseudocode) :
function doSomething (input) {
input.something(something);
do(input, function (res) {
input.send(res)
}
}
However, I want to be able to run it from another area, and the only shared variable between the two is $scope, so I do something like this:
$scope.doSomething = function (input) {
doSomething(input);
}
Now, I can call doSomething using $scope. However, creating an extra function to do it is quite messy. Ideally, I'd like to be able to do something like this:
$scope.doSomething = doSomething(input);
That doesn't work though. Is there a similar shorthand you can use to create a reference to a function from another, without the need for a 'useless' function?
You should be able to do that if you've already declared the function. But instead of using doSomething(input) which is actually calling the function, use it without the brackets like so
$scope.doSomething = doSomething;
what you need to do is assign function pointer.
$scope.doSomething = doSomething;
what you are currently doing $scope.doSomething = doSomething(input); is assigning function call result, rather than pointer

Redefining a function which is part of another function

I have a function that looks like this:
function outer() {
function inner_1() {
alert('inner_1');
}
function inner_2() {
alert('inner_2');
}
function inner_3() {
alert('inner_3');
}
inner_1();
inner_2();
inner_3();
}
I need to call outer(), but I want to replace inner_1() with another function.
I have tried this:
new_outer = outer;
new_outer.inner_1 = function() {
alert('my new inner function');
};
If I try to call the newly redefined inner_1 like this:
new_outer.inner_1();
it works as expected ('my new inner function' is alerted).
But if I try to call the outer function:
new_outer();
the old version of inner_1 is called.
I want to redefine inner_1 and the call outer. How can I achieve this?
This seems like a really bad idea so I am not going to post any code. However, if you are pursuing the answer for "educational purposes only", I will just hint that although you cannot easily redefine a function from outside its scope (as per your example), there is nothing stopping you from redefining a function attached to a function object.
I do think, however, there is a better solution to whatever the problem you are trying to solve is.

Javascript dynamically attaching functions to objects

How to attach a function dynamically to a javascript object.For ex: if the function for dynamic attachment is attach(),then i should be able to attach the function fn to onject obj as follows..
attach(
obj,fn,{
alert(1)
}
)
function attach(obj,fnName,code)
{
obj[fnName] = code;
}
If by "attach a function dynamically to a javascript object" you mean "add a function-object as an object property" then the syntax you've already shown is almost right. This is what it should be:
var fnName = "testFunc";
obj[fnName] = function() { alert("Test function"); };
// or
obj.testFunc = function() { ... };
// or
obj[fnName] = nameOfFunctionDefinedElsewhereInCurrentScope;
Which means you could call your attach() function like this:
// attach an anonymous function:
attach(obj, "newFunctionName", function() { alert(1); });
// attach a function defined elsewhere
attach(obj, "newFunctionName", someFunction);
Note: the attach() function really doesn't save any effort at all, in fact it just gives you more characters to type...
By the way (but don't do this), if the parameter you want to pass as code is a string of code do this:
var code = "alert(0);";
obj[fnName] = new Function(code);
More information: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function
EDIT : The other post's Function(code) solution appears better. I did not know about that constructor.
A possible solution may be:
Object.prototype.attach = function(name,code) {
this.name = function() {
eval(code);
};
}
You can attach them as function objects if they've already been defined, such as here: Javascript: better way to add dynamic methods?
You can also use the new Function constructor to dynamically define the functions, such as here: Creating functions dynamically in JS
Here is an explanation of the differences between eval and the new Function constructor: Are eval() and new Function() the same thing?
As a warning, use of eval() and the new Function constructor have created controversy and have been condemned (to some extent) by a number of individuals, such as here: Legitimate uses of the Function constructor
Here is more information about eval: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
Here is more information about the new Function constructor: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
Assuming that definition of function attach, you should call it like this:
attach(obj, fnName, function(){ alert(1); });
The way you invoked it is invalid syntax.
Also, as you may have noticed, that's not a very useful function, since you can do the same thing using your one-line function definition:
obj[fnName] = function(){ alert(1); });

javascript anonymous function parameter passing

I have some javascript code (within an object) :
toggle: function() {
var me = this;
var handler = function() { me.progress() };
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
I'm kind of new to javascript, so doing the above as far as I can tell actually passes the me variable into anonymous the function. I was wanting to see if there is a more declarative way to do so? I wanted something along the line of:
var handler = (function(o) { o.progress();})(this));
but that doesn't seem to be working... Am I missing something? Is this a case where "this is the way the language works so just declare a local variable and deal with it"?
UPDATE:
The source to my problem was/is my unclear understanding of scope and closures in javascript. I found this article to help me understand a little more.
You can use ".bind()":
var handler = function() { this.progress(); }.bind(this);
New browsers have "bind()", and the Mozilla docs have a solid implementation you can use to patch older browsers.
The reason
var handler = (function(o) { o.progress();})(this));
doesn't work because it just immediately calls the anon function, therefore immediately calling o.progress() and assigns the return value of the anon function (undefined) to handler. You need to return an actual function from the outer function:
handler = (function(me){
return function(){
return me.progress();
}
}(this));
On the flip side this is equivalent and just as bad looking as bad looking as the variable assignment (but can still be useful, particularly if this needs to be done in a loop, with the changing i rather than the fixed this).
BTW, if the progress function doesn't have any calls to this inside it , just doing handler = this.progress (without the parens) might suffice.
The anonymous function has access to me because it is declared inside of the outer function (the toggle function); it is closed over by the outer function.
Your handler function will be called by setInterval, which passes exactly zero arguments. This means you can't use parameters in the handler function itself.
I you really want to pass me explicitly, you could write a function accepting an parameter, and have that function return an anonymous function without parameters, but which could access the creator function's parameter:
toggle: function() {
var me = this;
var handler = (function (o) { return function() { o.progress() }; })(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
But this basically adds a layer of redirection without really making it more legible. Unless you pull that creating function outside:
function createProgressHandler(o) {
return function() {
o.progress();
};
}
// ...
toggle: function() {
var me = this;
var handler = createProgressHandler(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
What you have there is a closure. The function that is created and assigned to handler keeps a reference to the me object. This is normal, everyday JavaScript, and that's the way that closures work generally.
Have you tried to return the function like this?
var handler = function(o){
return function(){
o.progress();
}
}(me);
Now you can call:
handler();

Categories

Resources