Return value from nested function in JS - javascript

Super beginner here, I read the similar questions asked here and it did not solve my problem.
I know the instructions say that I'm only supposed to amend the final line (var burger...), but I cannot get this one to pass.
var food = function() {
return function() {
return "HAMBURGER"
}
}
var burger = food();
I want to return "HAMBURGER" but instead I return [Function]

The simplest thing you can do if you are only supposed to change the bottom line is to change it to:
var burger = food()();
Which is the equivalent of:
var burgerFunction = food();
var burger = burgerFunction();
Your function returns a function, so you need to invoke them both

As the function food returns an anonymous function, it has to be invoke to run and produce some result:
var food = function() {
return function() {
return "HAMBURGER"
}
}
var burger = food()(); // or food().call()
console.log(burger)
An interesting article about different ways of function invocation could be found here.

Related

How function reference works in js?

Recently I've been trying to use pixi.js for some fun project and I come across a concept that I do not understand at all. Quoting some code:
PIXI.loader
.add([
"images/one.png",
"images/two.png",
"images/three.png"
])
.on("progress", loadProgressHandler)
.load(setup);
function loadProgressHandler(loader, resource) {
console.log(`loading: ${resource.url}`);
};
How these arguments (loader, resource) are passed to the function since we only pass the reference to it in the event listener? Can someone show a generic implementation beneath that concept?
Lets say we have a function called callMe that just prints a number that its given:
function callMe(number) {
console.log(`I'm number: ${number}`);
}
callMe(2);
We can create a new variable to that same function, and call the newly created variable. This is possible since it's pointing to the same function that we've created earlier.
const callMeAswell = callMe;
callMe(3);
callMeAswell(4);
In short, this is what's happing inside the PIXI loaders, except for that it's stored somewhere else for you. Lets create a class to store the numbers and the function that we want to call:
function SomeLoader(){
this.numbers = []; // list of numbers we want to store for later usage
this.func = null; // function that we want to call when we're done loading
}
SomeLoader.prototype.add = function(number) {
this.numbers.push(number); // add the number to the list of numbers
}
SomeLoader.prototype.on = function(func) {
this.func = func; // just store the function for now, but don't do anything with it
}
SomeLoader.prototype.pretendToLoad = function() {
for(const number of this.numbers) {
this.func(number); // now we're going to call the function that we've stored (callMe in the example below)
}
}
const loader = new SomeLoader();
loader.add(5);
loader.add(6);
loader.on(callMe);
loader.pretendToLoad();
Or fluently:
function SomeLoader(){
this.numbers = [];
this.func = null;
}
SomeLoader.prototype.add = function(number) {
this.numbers.push(number);
return this;
}
SomeLoader.prototype.on = function(func) {
this.func = func;
return this;
}
SomeLoader.prototype.pretendToLoad = function() {
for(const number of this.numbers) {
this.func(number);
}
}
new SomeLoader()
.add(7)
.add(8)
.on(callMe)
.pretendToLoad();
Looks almost the same as the PIXI loaders, doesn't it? :)
Arguments are passed to the function when it is called.
The code which calls that function isn't in the question. It is done somewhere behind the on function.
In short: The same way as normal, you just aren't looking at the point where it happens.
const show = value => console.log(value);
const call_callback_with_hello_world = callback => callback("Hello, world");
call_callback_with_hello_world(show);
What #Quentin said is correct - adding on to that however...
A generic concept beneath that implemention is called a callback and would look like so:
function Loop(callback, index){
callback(index);
}
function CallbackFunction(val){
console.log(val)
}
for(var i = 0; i < 5; i++){
Loop(CallbackFunction, i);
}

Javascript: uncaught typeerror undefined is not a function for object methods

I make a simple quiz game. Here is some relevan methods that i have inside one object.
But doesn't work. I always get an error within 'rightAnswerGot' function. Console drops
"uncaught typeerror undefined is not a function for object methods" for this.addVariantsHtml(this.updateCharacter());
BasicGame.Game.prototype = {
actionOnClick: function (button) {
var log;
if(button.value==this.char_bubble.text) {
setTimeout(this.rightAnswerGot,1000);
} else {
// wrong
swoshsound.play();
}
console.log(log);
},
rightAnswerGot: function (){
this.addVariantsHtml(this.updateCharacter());
},
addVariantsHtml: function(id) {
this.answer = this.getAnswersVariants(id);
for (var i = 0; i < 6; i++) {
this.button[i].value = this.answer[i]['trans'];
this.button[i].char_id = this.answer[i]['id'];
this.ans_text[i].setText(this.answer[i]['trans']);
}
},
updateCharacter: function() {
var i = this.getRandomCharacter();
console.log("updateCharacter: "+i + " " +this.chars[i]);
this.char_bubble.setText(this.chars[i].getPath());
return i;
}
}
The aim is to froze the game for a second, when user choose the right answer, and than go to next question. Any ideas why does it happens?
Thanks
Looks like a classic JavaScript scope issue to me. However as you've tagged this question as using Phaser, I would suggest you use a Phaser Timer event to avoid scope problems. Specifically:
setTimeout(this.rightAnswerGot,1000);
replace it with:
this.game.time.events.add(Phaser.Timer.SECOND, this.rightAnswerGot, this);
Which will create a single 1 second timer that fires only once, calling your function at the end of it. You can use 1000 instead of Phaser.Timer.SECOND of course.
I would image that whats happening is that its trying to call the this.addVariantsHtml method, before its calling this.updateCharacter and getting the ID.
So your probably expecting that when it runs, for it to be something like:
this.addVariantsHtml(1);
But its actually trying to run
this.addVariantsHtml(this.updateCharacter());
So just do this:
var id = this.updateCharacter();
this.addVariantsHtml(id);
Either that or you need to look into method chaining/piping, which is just complicated and doesnt need to be used for this situation, but is interesting :)
Ok I found something that made it work!!
Here is a solution:
actionOnClick: function (button) {
var log;
if(button.value==this.char_bubble.text) {
var context=this;
setTimeout(function() {
context.addVariantsHtml(context.updateCharacter());
},1000);
} else {
// wrong
swoshsound.play();
}
console.log(log);
},

Javascript closure and handlers

I have this javascript function:
function files() {
var dropResult = false;
$('#button1').on('click', function() {
dropResult = true;
});
$('#button2').on('click', function() {
dropResult = false;
});
return dropResult;
}
files();
The dropResult variable must change after we click one of the buttons. How do I write it properly to make my function return the right value of dropResult variable?
I know, that it's about closures but I don't really understand how to fix this problem.
Thanks for help.
I believe you want
var files = (function () {
var dropResult = false;
$('#button1').on('click', function () {
dropResult = true;
});
$('#button2').on('click', function () {
dropResult = false;
});
return function () {
return dropResult;
};
})();
Demo at http://jsfiddle.net/gaby/9b7yK/
var dropResult = false;
$('#button1').on('click', function() {
dropResult = true;
});
$('#button2').on('click', function() {
dropResult = false;
});
function files() {
return dropResult;
}
Assuming all you need is to get the correct value for dropResult, the above code should work.
I will "extend" the answer of Gaby aka, but I think he is totally right. I will make only more specific in private and public methods. and how to access to them, and actually also bind the events to a specific button you can check the fiddle here [http://jsfiddle.net/qsDz6/][1]
HTML
<input type="button" id="button1" value="button 1" />
<input type="button" id="button2" value="button 2">
<input type="button" id="actualValue" value="Actual Value of _dropResult">
JS
var files = (function(__name){
var _name = __name;
var _dropResult = null;
/*Private */
function init(){
eventHandler();
}
function eventHandler(){
$(document).on("click","#button1", $.proxy($r.actionButton1,this));
$(document).on("click","#button2", $.proxy($r.actionButton2,this));
$(document).on("click", "#actualValue", $.proxy($r.dropResult,this));
}
/*Public */
var $r = {}; //will make public any method
$r.actionButton1 = function(){
_dropResult = true;
alert(_dropResult);
}
$r.actionButton2 = function(){
_dropResult = false;
alert(_dropResult);
}
$r.dropResult = function(){alert(_dropResult);}
init();
return $r;
})("files");
Happy coding
Update: Somehow this answer has been down-voted despite the fact that the most up-voted solution was posted at the same time, is equally elegant, and is logically equivalent. The other solution simply chooses to capture the local variable in a function closure rather than an object closure.
The responsibility of being a voter is to actually read and think about what these solutions do, rather than just voting for the answer provided by someone familiar or by the person with the highest reputation.
The responsibility that I have in answering is to only answer questions not for a popularity contest, but when (A) I know for certain a valid answer and am willing to take the time to explain and maintain that answer; or (B) for some discussion questions where there is nothing so clear-cut as the "answer," then only when I have encountered the issue many times in my experience and have something to say about it based on my actual experience.
For that reason, I am leaving my answer up (just as I have done in the past) even when someone in the community anonymously decides to downvote it without any explanation why.
Remember that the answers at Stack Overflow are intended to be a repository of useful solutions to useful questions, for the benefit of all programmers in the future. It is worthwhile to show two different approaches rather than a single one.
Yes, the other solution is elegant and demonstrates nicely capturing a local variable using an anonymous function closure. Yet, in my opinion, my solution is slightly better in the context of the purpose that Stack Overflow has, because this solution can be easily modified into a reusable function for creating many monitoring variables. The other solution would require a bit of deconvolution in order to make it useful for more than a single static instantiation of one monitoring function.
function files() {
var dropResult = {};
$('#button1').on('click', function() {
dropResult.result = true;
});
$('#button2').on('click', function() {
dropResult.result = false;
});
return dropResult;
}
var dropObject = files();
The variable dropObject is a "monitoring variable" that can be used anywhere in order to check the status of what you are monitoring (in this case, which alternative the user last specified by their most recent click on either button1 or button2.)
In code that uses the result from files() you can do this
if (dropObject.result) {
/* do something here that you want to do when the result is true */
} else {
/* do something here when the result is false */
}
I would suggest storing something more meaningful than true or false (what if you wanted to add a third button and then monitor which of the three had last been clicked, for example?).
Note: Here is how I would write a smaller, more efficient reusable monitoring function for my use (not hard-wiring any parameters or names inside the function) and apply it to this scenario:
function clickMonitor(ids) {
var i, f = function() { i = this; }; ids = ids.match(/(\S+)/g) || [];
for (i=0; i<ids.length; i++)
document.getElementById(ids[i]).onclick = f;
return function() { return i; };
}
This next part just creates a dropResult variable that would be
"plug and play" in place of your dropResult variable, except that you
would have to check to see if dropResult() is true or false
(function invocation) rather than just dropResult.
dropResult = (function() {
var x = clickMonitor('button1 button2');
return function() { return x().id == 'button1'; };
})();
In general, this is how you would use it (more than two button IDs can be passed to it, of course, if wanted):
getMostRecentClickedButton = clickMonitor('button1 button2');
Calling getMostRecentClickedButton() returns the entire button
object most recently clicked so that you can do something with it, like
make the font bold, etc., without needing to perform another intermediate
jQuery or JavaScript procedure.
I don't understand the need for this but one way would be
function files() {
files dropResult = false;
return files.dropResult;
}
$(document).on('click', '#button1', function() {
files.dropResult = true;
});
$(document).on('click', '#button2', function() {
files.dropResult = false;
});
files();

Calling functions in two different ways - JavaScript

I'm very new to JavaScript, so my apologies if this answer is glaringly obvious or I'm barking up the wrong tree!
What's the difference in the following code snippets:
function primeAddNum(innerHTML) {
return function() {
addNum(innerHTML);
return false;
};
}
var func = primeAddNum(innerHTML);
The second one:
var func = function() {
return function() {
addNum(innerHTML);
return false;
};
}();
The top one works the way I'd like it to, but not the bottom, but that's not overly important to me. What I want to know is the logic behind each block, because I just can't see the difference!
The problem with the second block is that innerHTML is undefined there, since you're not passing it. They will become equivalent if you change it to:
var func = function(innerHTML) {
return function() {
addNum(innerHTML);
return false;
};
}(innerHTML);
Well with the second one you can only create a func once. But with first one, you can create many:
var func1 = primeAddNum(innerHTML);
var func2 = primeAddNum(someOtherInnerHTML);
there is no difference, you can use both without any problems

JavaScript - from alert to function

I'm very new on my quest for learning JavaScript(only two weeks) so be nice and surprised how far I got.
What I’m trying to do is hit a button and the button will evoke a random image or div to come to the front. I as you see I use the z-index by moving elements from back to front.
I have got far enough to create an alert that tells me it does find the random function just cant get it to activate this function (the changeCombined functions do work fine when I assign it to a button but just can’t get the getImage to run).
I’m unsure if it is possible, and I know there might be a hundred better ways to do this but one step at a time.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;
};
var changeCombined1 = function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
var changeCombined2 = function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
function get_random(){
var ranNum= Math.floor(Math.random()*2);
return ranNum;
}
function getImage(){
var whichImage=get_random();
var image=new Array()
image[0]=changeCombined2;
image[1]=changeCombined1;
alert(quote[whichImage]);
}
Try this:
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;
};
function getImage(){
var whichImage=Math.floor(Math.random()*2);
var image=new Array()
image[0]=function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
image[1]=function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
image[whichimage]();
alert(quote[whichImage]);
}
To invoke a function you should use either apply or call methods.
Have you tried image[whichImage].apply(undefined) instead of your alert ?
You are not calling the changeCombined() functions at all.
If you are trying to call the functions, you have to use ()
image[0]=changeCombined2();
image[1]=changeCombined1();
What you have just the functions themselves to image[0] and image[1].
So after
x = changeCombined2;
x will hold a reference to the changeCombined2 function itself. So now if you say x() (or in your case image[0]()), it will call changeCombined2.
() will call the functions and will put the return value of the function into the array elements.
Note: since the functions do not explicitly return anything, image[0] and image[1] will hold undefined.
Thanks for all the help to get past my road block, the rookie mistake of not calling my funcions was the biggest issue. I was able montage the comments to create this version that works as expected.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;};
function getImage(){
var whichImage=Math.floor(Math.random()*2);
var image=new Array()
image[0]=function() {
changeZIndex(-5,"scene2");
changeZIndex(5,"scene1");
};
image[1]=function() {
changeZIndex(-5,"scene1");
changeZIndex(5,"scene2");
};
image[whichImage].apply(undefined);};

Categories

Resources