Calling functions in two different ways - JavaScript - 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

Related

Return value from nested function in JS

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.

Getting correct scope in functions (not using that = this)

I am trying to fix a function I have here to be able to use it without using a that = this (or self = this as some like to use). It is a scoping issue but I am not sure how to get around it, and I would like to get in the habit of not using a that = this . So the functions are all in a return (angular factory) and I am having trouble referencing another function . Let me show you what I mean :
return {
loadStates: function() {
var that = this;
//chgeck if is loaded module, then change and fire callback
var currentModules = moduleHolder.getModules();
if (currentModules[name]) {
//works here
this.prepState();
} else {
//module cannot be found check for 5 seconds
$log.warn("Requesting " + name + "...");
var timeToCheck = true;
setTimeout(function() {
timeToCheck = false;
}, 5000);
var check = {
init: function() {
check.checkAgain();
},
checkAgain: function() {
if (timeToCheck) {
if (currentModules[name]) {
//but not here
that.prepState();
} else {
//still doesn't exists
setTimeout(check.checkAgain, 200);
}
} else {
//doesn't exist after 5 seconds
$log.error("Requested module (" + name + ") could not be found at this time.");
}
}
};
check.init();
}
},
prepState: function() {
}
}
So in the top if it finds the currentModule[name] I can use a this.prepState() and it works fine. However inside the timing functions I cannot use the this anything because it is inside a different scope so I have temporarily gotten around this by setting a that = this up top, however I would like see if I could not use this method. How does one get around this without using the that= this? Thanks!
It is a scoping issue...
No, it isn't. this and scope have essentially nothing to do with each other. (For now; ES6's arrow functions will change that.) It's an issue of how the functions are called.
If you pass a function reference to something that will call it later, unless the thing you're passing it to has a way you can use to tell it what to use for this when calling it, your function will get called with this not referring to what you want it to refer to.
You can get a new function reference that will call your original function with the correct this by using Function#bind:
var usesCorrectThis = originalFunction.bind(valueForThis);
So for example, suppose I have:
var check = {
name: "Fred",
sayHello: function() {
console.log("Hi, I'm " + this.name);
}
};
If I do:
check.sayHello();
All is good: Calling the function as part of an expression retrieving it from a property tells the JavaScript engine to use the object as this during the call.
However, if I do:
setTimeout(check.sayHello, 0);
...that doesn't work right, because when setTimeout calls the function, it doesn't use the right value for this.
So I can use Function#bind to address that:
setTimeout(check.sayHello.bind(check), 0);
More (on my blog):
Mythical methods
You must remember this
there are different ways you can do that.
One way is to use bind function.you can use
var checkInitBindFn = check.init.bind(this);
checkInitBindFn();
Secondly you can use call and apply also.
check.init.call(this);
check.init.apply(this);
Like this you can use this instead of that.
Check the complete api doc online...
It's not a scoping issue. If you want to avoid self = this you can always reference functions by objects. Makes cleaner code and since factories in angular are singletons you're not wasting memory.
angular.module('myApp').factory('myFactory', function ($timeout) {
var myFactory = {
loadState: function () {
$timeout(function () {
myFactory.check();
}, 500);
},
check: function () {
},
};
return myFactory;
});

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();

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);};

Overriding a JavaScript function while referencing the original

I have a function, a(), that I want to override, but also have the original a() be performed in an order depending on the context. For example, sometimes when I'm generating a page I'll want to override like this:
function a() {
new_code();
original_a();
}
and sometimes like this:
function a() {
original_a();
other_new_code();
}
How do I get that original_a() from within the over-riding a()? Is it even possible?
Please don't suggest alternatives to over-riding in this way, I know of many. I'm asking about this way specifically.
You could do something like this:
var a = (function() {
var original_a = a;
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})();
Declaring original_a inside an anonymous function keeps it from cluttering the global namespace, but it's available in the inner functions.
Like Nerdmaster mentioned in the comments, be sure to include the () at the end. You want to call the outer function and store the result (one of the two inner functions) in a, not store the outer function itself in a.
The Proxy pattern might help you:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
The above wraps its code in a function to hide the "proxied"-variable. It saves jQuery's setArray-method in a closure and overwrites it. The proxy then logs all calls to the method and delegates the call to the original. Using apply(this, arguments) guarantees that the caller won't be able to notice the difference between the original and the proxied method.
Thanks guys the proxy pattern really helped.....Actually I wanted to call a global function foo..
In certain pages i need do to some checks. So I did the following.
//Saving the original func
var org_foo = window.foo;
//Assigning proxy fucnc
window.foo = function(args){
//Performing checks
if(checkCondition(args)){
//Calling original funcs
org_foo(args);
}
};
Thnx this really helped me out
You can override a function using a construct like:
function override(f, g) {
return function() {
return g(f);
};
}
For example:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a(); }
else { original_a(); other_new_code(); }
});
Edit: Fixed a typo.
Passing arbitrary arguments:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a.apply(this, arguments) ; }
else { original_a.apply(this, arguments); other_new_code(); }
});
The answer that #Matthew Crumley provides is making use of the immediately invoked function expressions, to close the older 'a' function into the execution context of the returned function. I think this was the best answer, but personally, I would prefer passing the function 'a' as an argument to IIFE. I think it is more understandable.
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
The examples above don't correctly apply this or pass arguments correctly to the function override. Underscore _.wrap() wraps existing functions, applies this and passes arguments correctly. See: http://underscorejs.org/#wrap
In my opinion the top answers are not readable/maintainable, and the other answers do not properly bind context. Here's a readable solution using ES6 syntax to solve both these problems.
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
I had some code written by someone else and wanted to add a line to a function which i could not find in the code. So as a workaround I wanted to override it.
None of the solutions worked for me though.
Here is what worked in my case:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}
I've created a small helper for a similar scenario because I often needed to override functions from several libraries. This helper accepts a "namespace" (the function container), the function name, and the overriding function. It will replace the original function in the referred namespace with the new one.
The new function accepts the original function as the first argument, and the original functions arguments as the rest. It will preserve the context everytime. It supports void and non-void functions as well.
function overrideFunction(namespace, baseFuncName, func) {
var originalFn = namespace[baseFuncName];
namespace[baseFuncName] = function () {
return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
};
}
Usage for example with Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
// ... do stuff before base call
baseFn(obj);
// ... do stuff after base call
});
I didn't create any performance tests though. It can possibly add some unwanted overhead which can or cannot be a big deal, depending on scenarios.
So my answer ended up being a solution that allows me to use the _this variable pointing to the original object.
I create a new instance of a "Square" however I hated the way the "Square" generated it's size. I thought it should follow my specific needs. However in order to do so I needed the square to have an updated "GetSize" function with the internals of that function calling other functions already existing in the square such as this.height, this.GetVolume(). But in order to do so I needed to do this without any crazy hacks. So here is my solution.
Some other Object initializer or helper function.
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
Function in the other object.
updateToolbarButtons = function(viewer) {
var _viewer = viewer;
return function(width, height){
blah blah black sheep I can refer to this.anything();
}
};
Not sure if it'll work in all circumstances, but in our case, we were trying to override the describe function in Jest so that we can parse the name and skip the whole describe block if it met some criteria.
Here's what worked for us:
function describe( name, callback ) {
if ( name.includes( "skip" ) )
return this.describe.skip( name, callback );
else
return this.describe( name, callback );
}
Two things that are critical here:
We don't use an arrow function () =>.
Arrow functions change the reference to this and we need that to be the file's this.
The use of this.describe and this.describe.skip instead of just describe and describe.skip.
Again, not sure it's of value to anybody but we originally tried to get away with Matthew Crumley's excellent answer but needed to make our method a function and accept params in order to parse them in the conditional.

Categories

Resources