Struggling to understand how the value of certain function parameters are determined - javascript

I often do not understand how the value of certain function parameters is determined. Take the following code snippet for example:
function gotItAll(res) {
$('#actionscreen').modal('hide')
if (res.ErrorHtml != "" && res.ErrorHtml.substring(0,31) != "Error copying to sub data table") {
document.getElementById('GridView').innerHTML = res.ErrorHtml;
InfoMessage("Error", res.ErrorHtml);
} else {
if (res.BrowseTreeBreadCrumbs != null) {
//generateBrowseTreeHtml(res);
sessionStorage.setItem("browseTreeBC", res.BrowseTreeBreadCrumbs);
if (res.BrowseTreeBreadCrumbs.indexOf("-1") > 0 || res.BrowseTreeBreadCrumbs.indexOf("- -1") > 0 || res.BrowseTreeBreadCrumbs.indexOf("- -999") > 0 || res.BrowseTreeBreadCrumbs.indexOf("-999") > 0 || res.BrowseTreeBreadCrumbs.indexOf("-999") > 0 || res.BrowseTreeBreadCrumbs.indexOf("</b> </span") > 0) {
$('#breadCrumbsID').hide();
}
}
BaseTable = res.TableName;
recs = res.records;
'res' is a parameter that I could not find defined anywhere, yet it returns a value. I was not able to identify where gotItAll() is called and passed a value other than res. In addition, we have res.ErrorHtml, res.BrowseTreeBreadCrumbs.indexOf, res.TableName etc. that do not appear to be defined anywhere, yet they all return different values.

res is passed in from whatever calls gotItAll
The res.whatever are the attributes of the res object
The name res is just for use in that function, and will likely have a different name to what was used as the parameter.
Example
funciton addOneToNumber(numberToAddTo)
{
return numberToAddTo += 1;
}
function mainFunction()
{
var newNumber = addOneToNumber(1)
}
Edit:
You can use any object in javascript to be used as a parameter. In this case the function has been used. It also looks like failedCallback is also a function. Which would be called if the call to the server fails
Inside InventoryEditor.ItemEdit.AddNew somewhere, gotItAll is called with res which would of been a result of the server call from whichever type of call is made

The code snippet you posted is just the function declaration. Basically that snipper defines the existence of a function called gotItAll, which takes one parameter as the input. The parameter is called res, so inside the function, the word res refers to the parameter of the function.
Let's use a simple function as example:
function double(x) {
return x * 2
}
This function as a parameter as well, called x. Inside the function, you refer to it as x.
When you want to use the function, you call the function and you gave a parameter, such as:
double(2) // returns 4
double(4) // returns 8
double(7) // returns 14
As you can see, we can pass to the function double different values. When you call double(4), basically the function considers x = 4, and so everytime inside the function declaration you use x, you will be using the value 4 instead.
You can also pass different variables to the function:
var y = 10
double(y) // returns 20
Same as before, you give to the function the variable y, whose value is 10. So basically the program does x = y and everytime it refers to x inside the function declaration, it will be using the value of y.
Back to your example. I don't know what that function do, but basically res is the placeholder name of the parameter that will be passed to the function. That function can be called from around the code as gotItAll(variableName), and the function will be executed considering res = variableName. In the snipper you pasted, the function is only declared but there are not examples of actual usages of the function, that's why you can't see where res comes from.
EDIT: after your comment, I realized what you are actually referring to. Actually, in Javascript you can pass functions as the parameter of another function. Take for example the double function declared above. Now I want to create a function that doubles the number only if they are even. I can declare this:
function doubleEven(x, doublingFunction) {
if (x % 2 === 0) {
return doublingFunction(x)
} else {
return x
}
}
and I can use it as:
doubleEven(2, double) // returns 4
doubleEven(5, double) // returns 5
Basically, I pass double as a parameter to the doubleEven function. So, inside the doubleEven declaration, doublingFunction becomes equal to double and so it is a function.
Of course in this example this is silly, there is no need to pass a function for doubling a number. However this is used a lot in javascript to provide a callback to asynchronous task, such as a network request.

Related

eloquent javascript - Closure and Functions

In eloquent JavaScript, the author provides the following example + prose:
With a slight change, we can turn the previous example into a way to
create functions that multiply by an arbitrary amount.
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
var twice = multiplier(2);
console.log(twice(5));
// → 10 The explicit
localVariable from the wrapValue example isn’t needed since a
parameter is itself a local variable.
Thinking about programs like this takes some practice. A good mental
model is to think of the function keyword as “freezing” the code in
its body and wrapping it into a package (the function value). So when
you read return function(...) {...}, think of it as returning a handle
to a piece of computation, frozen for later use.
In the example, multiplier returns a frozen chunk of code that gets
stored in the twice variable. The last line then calls the value in
this variable, causing the frozen code (return number * factor;) to be
activated. It still has access to the factor variable from the
multiplier call that created it, and in addition it gets access to the
argument passed when unfreezing it, 5, through its number parameter.
how does javascript know that the 5 in:
console.log(twice(5));
is suppose to be the value for number? Is JavaScript essentially saying to itself "I already have 2 as the value for factor, and I can't change that, so 5 has to be the value for number".
In other words
var twice = multiplier(2)
so twice = multiplier(2) {return function (number)}
thus twice(5) = multiplier(2) {return function (5)}
Is this right?
if there was another local variable inside multiplier, could I call:
twice(5,10)
and javascript would know that means:
factor = 2
number = 5
third variable = 10
ES6 VERSION
const multiplier = factor => {
return number => number * factor;
}
The part that confused me was thinking that the variable 'twice' was being assigned the multiplier function, rather than the return of the multiplier function (which is also a function).
const twice = multiplier(2);
So what is actually being assigned is:
const twice = number => number * 2
twice(2)
-> 10
Think of it as this :
var twice = function(number) {
return number * 2;
};
When you call multiplier(2) you are creating a new function that embeds factor into that new function.
I was stuck on this for a bit as well. Here's what helped it click for me.
On the book's website, you can interact with the code on the page:
https://eloquentjavascript.net/03_functions.html#p_O3ISvGjNhj
I tried removing the arguments from the twice variable:
function multiplier(factor) {
return number => number * factor;
}
let twice = multiplier(2);
console.log(twice);
This returned: number => number * factor
That helped me realize that twice is being assigned the inner function of multiplier. When I don't pass an argument, it returns the inner function itself. When I pass an argument to twice, it becomes the argument of that inner function, and executes it.
So when I tried this:
console.log(twice());
It attempted to execute the function. And it returns NaN because I didn't pass an argument for number.
So, when we do this:
let twice = multiplier(2);
We are binding the variable twice to the inner function of the multiplier function with (effectively) an argument of 2 passed.
The previous comments explained this operation much more succinctly, but it didn't quite make sense to me until this clicked.

understanding the object passed in two contexts

I don't know if you've ever felt like you've dived off the stupid tree and hit every branch on the way down, but JavaScript has that effect on me, an experienced PHP programmer but just doesn't get JS sometimes.
so I wrote this function using jQuery.extend({ .. }) as follows:
loadSection: function(obj){
if(typeof obj=='undefined')obj=event.target; //but this doesn't work
if(typeof obj=='string')obj=document.getElementById(obj);
var params=null;
var instr={};
var k=0;
while(true){
..etc..
I want to be able to call it two ways:
$.loadSection($('#employee-data-173'));
//or $loadSection('employee-data-173') for convenience
or:
$('#employee-data-173').loadSection();
Clearly (to you anyway!) I'm not grasping the concept of what's being passed in the second case. And that's not even getting into a case like this:
$('.someElement').click(loadSection);
You want to use the same function in three totally different usecases. In each case different arguments are automatically passed to the function. So first declare and prepare it to handle all possible types of arguments:
function loadSection(index, obj, args) {
var element, params = null;
if (obj && obj.nodeType) { // for usecase 2
element = obj; if (typeof args == 'object') params = args;
} else {
if (typeof obj == 'object') params = obj;
if (typeof index == 'string') { // usecase 1 with selector-string
element = document.getElementById(index);
else if (index.jquery) { // usecase 1 with jQuery object
if (index.length == 1) element = index[0]; // if only one element inside jQuery
// if more than one element there call this function recursively on each
else index.each(loadSection);
}
else if (index.target) element = index.target; // for usecase 3
}
/* your stuff */
}
In your usecase 1 you have to add the function to the global jQuery object and call it by $.loadSection(argument), where argument may be a id-selector-string or an jQuery-object $("selector"). There are two ways with identic result:
$.loadSection = loadSection;
$.extend({loadSection: loadSection});
In usecase 2 you want to call the function as a method of a jQuery object. Therefore you have to add it to the jQuery.prototype like so:
$.fn.loadSection = function( args ) { // $.fn is synonym for jQuery.prototype
return this.each(loadSection, args);
};
If you call now $("selector").loadSection() the function is executed once for each element matched by "selector". Arguments index and obj are automatically passed to loadSection.
In usecase 3 the function is used as callback-function for an event. Since its prepared for this case, the event object is automatically passed to it. So just do:
$('.someElement').click(loadSection);
You can use all cases mixed in the same piece of code.
EDIT "What shall/can the function return?"
It may return whatever you want to. Only the behaviour depends on usecase.
In usecase 1 you can do: var result = $.loadSection("selector") and result gets the returned value.
In usecase 2 there is an iteration over all elements in the jQuery object. The return value of loadSection is simply ignored except you explicitely return false. Then iteration stops. So if you do if (index == 2) return false; the function is executed maximum 3 times even when you have 7 elements inside jQuery object.
The function as a whole always returns the jQuery object, so you can do chaining:
$("selector").loadSection().css({color: 'blue'}).animate(...). ...
In usecase 3 the function is only executed but the return value gets never recognized anywhere, so you can't catch it.
EDIT 2 "How to pass additional params to the function?"
1) Now loadSection is prepared to take additional args (see above). 2) The setup of $.fn.loadSection is modified to take args (see above). 3) args must be an object or array eg {prop: 'color', id: 23} (otherwise it's ignored) but may be omitted.
In usecase 1 pass args as second argument
var result = $.loadSection("selector", args); // you find args inside in ""var params"
In usecase 2 args is the one and only possible argument. jQuery now makes an iteration inside an iteration: the function is called on each element once for each item in args!
The inner iteration is stoppable by return false, but the iteration over all elements no longer.
$("selector").loadSection({prop: 'color', id: 23}) // if $() contains 3 elems, function run six times
In usecase 3 its impossible to pass args since you only point to the function by its name.

Javascript - Math.random as parameter

I asked this before, but a little vague and poorly worded.
I have a object that takes in Actions and puts them into a stack that it goes through over time. It performs the first Action in the stack until it's done, then it performs the second, and so on. There is a RepeatAction that can take in an array of other Actions and perform them a number of times in a similar fashion. (.repeat() simply puts a new RepeatAction into the objects stack.
Take this for example:
object.repeat(10,[new LogAction(Math.random())]);
Given that LogAction only takes in a parameter and logs it out. When the object's repeat function gets called it will put 10 LogActions into its stack, but they will all log the same number. What I'm looking for is a way that it will log a different number all 10 times.
You may say just pass in Math.random as a function, but then what if I want to pass in 4 * Math.random()?
Any help?
The code needs to invoke a function (later) to get a different value. e.g.
// pass in the `random` function - do not get a random number immediately!
object.repeat(10, [new LogAction(Math.random)])
// create and pass in a custom function that uses `random` itself
var rand4 = function () { return Math.random() * 4 }
object.repeat(10, [new LogAction(rand4)])
Since "LogAction" is not disclosed, I'll make a simple example to work with the above.
function LogAction (arg) {
this.execute = function () {
// If the supplied argument was a function, evaluate it
// to get the value to log. Otherwise, log what was supplied.
var value = (typeof arg === 'function') ? arg() : arg;
console.log(value);
}
}
Reading through How do JavaScript closures work? will likely increase the appreciation of functions as first-class values, which the above relies upon.
You may say just pass in Math.random as a function,
Yes, I would.
but then what if I want to pass in 4 * Math.random()?
Then in place of Math.random, use
function() { return 4 * Math.random(); }
You can pass function which returns result of random:
object.repeat(10,[new LogAction(function(){return Math.random();})]);
And in LogAction function you simply need to check if argument is a function:
function LogAction(arg){
var value = arg&& getType.toString.call(arg) === '[object Function]' ? arg() : arg;
//log value
}

handle empty object passed as argument in javascript

Good day all.
I have this problem: I must provide a way to pass some optional arguments to a javascript function, this is pretty easy, ok. I decide to make all the arguments be an object, so anyone who need to call the function must provide the name of the arguments. But most of the time, the editors simply call the functions with the whole argument object, without omitting the empty arguments, because arguments are passed to the page via another way (let's say in the querystring, but it doesen't matter).
here it is how I have made the function:
function playAnimation(options) {
var timeOutAnimation = options.animationDuration || 15;
var backgroundColor = options.color ; // this argument will be always present, so no default.
//more code...
}
and this is the call (I use a php code for example purposes)
$(document).ready(function(){
var opt = {
animationDuration: '<?php echo $_GET['stopAnimationAfter'] ?>', //could be a number, or nothing.
color: 'black'
}
playAnimation(opt);
});
the problem is that the argument is passed and it seams that it never falls on the default value. I can't change the way the function is called (i.e. checking the avialability of the "get" parameter and build the function call accordingly, I must find a way to test the arguments inside my javascript.
is there a safe way to do so, like options.animationDuration === "undefined" (doens't work) or something?
SOLUTION: putting ' ' around each argument in the call, makes the argument be full or empty accordingly. and then i can test them.
You can use:
function playAnimation(options) {
options = options || {}
var timeOutAnimation = options.animationDuration || 15;
var color = options.color;
}
To set options to an empty object if it doesn't exist. You can also check for undefined like this if you want:
if(typeof options === "undefined") {
// options not passed
}
Here is a fiddle which demonstrates.

Setting a JavaScript function as a parameter for use with another function?

I'm learning lots of javascript these days, and one of the things I'm not quite understanding is passing functions as parameters to other functions. I get the concept of doing such things, but I myself can't come up with any situations where this would be ideal.
My question is:
When do you want to have your javascript functions take another function as a parameter? Why not just assign a variable to that function's return value and pass that variable to the function like so:
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
I'm confused as to why I would ever choose to do things as in my second example.
Why would you do this? What are some use cases?
Here's yet another example. Does some formatting operations on an array:
function pctFormatter(num) {
return num + '%';
}
function centsFormatter(num) {
return num + '.00';
}
function formatThisArray(array, formatter) {
var output = [];
for(var i = 0; i < array.length; i++) {
output.push( formatter(array[i]) );
}
return output;
}
formatThisArray([1,2,3], pctFormatter);// returns ['1%', '2%', '3%']
formatThisArray([1,2,3], centsFormatter);// returns ['1.00', '2.00', '3.00']
Handlers/listeners are a good example.
More generally, you can pass a function f as a parameter to function g when you don't know yet if g will need to call f, how many times it will need to call it, and/or with which parameters.
Examples:
sort algorithms: comparison function
regular expressions: replace function
callbacks (e.g. event handlers)
You'd do it when you don't have the params to pass, but the callerFunction() does.
A callback to an AJAX request is one use case.
function myCallback(response) {
// do something with the response
}
myAJAX('http://example.com/foo.json', myCallback)
This lets myAJAX to the work of making the request, and waiting for the response. Then it invokes myCallback and passes it the response when that response finally arrives.
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
First example will run the function doStuff with params and the assign the result to foo. callerFunction will be called with parameter foo (which is now a result of dooStuff);
Second example will call callerFunction and pass doStuff as a parameter. The callerFunction might or might not call the doStuff.
Well, sometimes you don't know who the caller of a function will be until it's called - this precludes passing pre-calculated values.
A couple of examples that spring to mind are:
(a) setTimeout or setInterval - you want to call a specific function after a specified period, either one-shot, or repeatedly. If the function called returned a value that had a dependance on time, there are instances where you couldn't possibly pre-calculate the value - it needs to be done at the scheduled time. So, we tell the functions which of our own functions to call at the specified time.
(b) when loading (or at least attepmpting to) various resources. We can give the element a function that is to be executed when loading is successful, and another when it fails. You don't actually know when the effort to load a resource has finished until either of these two (user-supplied) functions are called. In the case of many resources, this is where you increment the counters that maintain the number of successful/failed load attempts.
(c) the NodeList returned by calls to getElementsByClass or getElementsByTagName. It's not an actual (javascript native) Array object. As such, you can't call the forEach method on it, like you can with an array. To get around this, I use the following helper function:
// getElementsByTagName, getElementsByClass - both return a NodeList
// it is accessed in the same way as an array - with the [] operators, but it's
// not an array object - this is a function that allows us to still iterate through it
// in much the same way.
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
This allows me to get a list of nodes and then call some user-defined function on each of them. In use, it looks like this:
var allAnchors = document.getElementsByTagName('a');
forEachNode(allAnchors, showNodeTextVal);
function showNodeTextVal(curElem, curIndex, origList)
{
alert(curElem.innerText);
}
Or more simply:
var allAnchors = document.getElementsByTagName('a');
forEachNode(allAnchors, function(curElem){alert(curElem.innerText);} );
This is a much clearer, less error-prone situation than it would be if we didn't use this helper function. To achieve the same functionality, we'd need to code the following:
var nodeList = document.getElementsByTagName('a');
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
alert(nodeList[i].innerText);
}
Most common case is handlers in JQuery:
function clickHandler(e){
// handle click on e.Target
}
$("#button").click(clickHandler);
$(function(){
// do ready state initialization
});
callerFunction(doStuff);
with this code you give a "pointer" of the function doStuff to the function callerFunction
you can use it like this:
function callerFunction(doStuff) {
var x = doStuff(...);
...;
}
you can so use the function in the function and not only the return value of doStuff.
greetings!
When do you want to have your javascript functions take another
function as a parameter?
It's useful for callbacks for example:
function add( a, b, callback ) {
callback( a, b );
return a + b;
}
function added( a, b ) {
alert('You just added two numbers: '+ a +' and '+ b);
}
alert( add( 1, 2, added ); // Will alert the message and then the result.
This a very simple example but it's very useful with asynchronous functions so you can run code after it has finished without interrupting the script.
You need to pass functions themselves, not return values, when you want to have your code really deal with functions as functions - code to execute. Consider this pseudo-code example:
function saveToLocalStorage(data) {...//saves to local storage}
function saveToServer(data) {...//saves via AJAX to server}
function saveToAmazonS3(data) {.../saves to Amazon S3 }
function multiSave(data, saverFunctions) {
saverFunctions.forEach(function (saverFunction) {
saverFunction(data);
});
}
multiSave({user: "tim"}, [saveToLocalStorage, saveToServer, saveToAmazonS3]);
In this case, I want the actual functions themselves to be passed around and for other code to later invoke them. When we do this, a function such as multiSave is called a higher-order function because it deals with other functions directly. Because of the way multiSave works, I can easily put some checkboxes in the UI next to local/server/S3 and allow the user to choose where their data goes in a way that would be less elegant if I was unable to pass functions around as arguments.
When you're passing a function as an argument, that argument is not the return value of that function, but it's the function itself, you can call it as much as you like, with any argument you like, or you can assign it to an event. You say you want some practical use cases, here's a short list of very common situations, all requiring a function to be passed as an argument.
Let's take a look at your average jQuery code, and count the number of times where a function is passed as an argument:
$(document).ready(function()//<-- 1
{
$('#foo').on('click',function()//2
{
});
$.each(something,function()//3
{});
//and so on
});
If you don't use jQuery, then try event delegation
document.body.addEventListener('click',function(e)
{
e = e || window.event
console.log('This function was passed as an argument to the addEventListener method');
},false);
Or even the simple Array.prototype.sort function (/method):
anArray.sort(function(a,b)
{
return (a > b ? 1 : -1);
});
Or in cases where you need to make an ajax call, instead of creating a new XMLHttpRequest object on the spot, you might want a single function that sets the xhr object up, and pass the url, data and onreadystatechange callback as arguments:
function makeXHR(url,data,callback)
{
try
{
var xhr = new XMLHttpRequest();
}
catch(e)
{
//etc...
}
xhr.onreadystatechange = callback;
}
makeXHR('some/url','foo=bar',function()
{
if (this.readyState === 4 && this.status === 200)
{
//do stuff
}
});
In all of these examples, I've created the functions in-line, of course referencing a function (by just passing its name) works just fine, too:
makeXHR('some/url','foo=bar',defaultXhrCallback);
These are just a few of thousands of use cases where you can/have to pass a function as an argument to another function

Categories