Function - Passing the arguments. - javascript

I have a large code base, and I am tasked to implement additional functionality. Code is Node.js - Javascript.
There is one function, and it goes like this:
function checkPeople(first, second) {
if(second) {
//do some things...
}
}
That same function is called several times, but generally it is called like:
checkPeople(first);
or...
checkPeople(first, second);
It depends what is being used for. the parameter "first" is always send regardless.
Now I have to add extra functionality to the same function but with the third parameter:
function checkPeople(first, second, third) {
if(second) {
//do some things...
}
if(third) {
//do some things
}
}
I was thinking to add third parameter to the function, wherever the function is being called (around 2 times), and check for the existance of the parameter inside the function. Which it is already done for the the parameter "second".
Is this approach valid?
Thank you

If you pass in the argument like this when you call the function, using null as the second argument, it will not call the second. Assuming that is what you are trying to do. checkPeople(first, null, third)

I'm going to be making an assumption here, but since the function is called checkPeople i'm going to assume you're doing the same check for every person (for instance: check for every person if he... exists?)
If that is the case:
function checkPeople()
{
var people = Array.prototype.slice.call(arguments);
return people.map(function(person) {
return person == 'eric'; // only eric is a person today
});
}
Now, you can do this:
var results = checkPerson('eric','peter','james'); // [true, false, false];
var result = checkPerson('eric'); // [true]
var result = checkPerson('james'); // [false]
If there are actually different checks for a first, second, and third parameter, then you indeed still have to implement the if (second) { .. } checks.

Related

Using setInterval() function to make pomodoro timer

My code is bellow, it doesn't throw errors but it stops after running ones.
I tried reviewing this codes and searching through documentation, but couldn't find anything, possibly due to my level of knowledge.
var timeNumbers = ['count','working','resting'];
var amountData = {'count':0,'working':0,'resting':0};
function fromCount(){
if(timeVa['working'] == false) return;
var amountDataNo1 = Array.from(amountData);
var dataW = setInterval(loseTimeW(1),1000);
function loseTimeW(n){
if(amountDataNo1[timeNumbers[n]] == 0){
clearInterval(dataW);
timeVa['resting'] == true;
}else{
amountDataNo1[timeNumbers[n]]--;
}
}
}
The first argument of setInterval() is the function it must invoke periodically.
The first argument you pass to setInterval() is the value returned by the call loseTimeW(1). But the loseTimeW() function does not return anything, consequently the value of loseTimeW(1) is undefined.
I guess your intention is to invoke loseTimeW() with argument 1 every 1000 milliseconds. You can achieve this easily. setInterval() accepts two or more arguments. It passes the arguments starting with the third one (if any) to the callback (argument #1) when it invokes it.
The working code is something like:
var dataW = setInterval(loseTimeW, 1000, 1);
Read more about setInterval().

Cant run code and function call passed as string inside settimeout

I want to run code using settimeout.
I have this function:
function passing_functions(thefunction)
{
var my_function ="res="+thefunction+ "(); if (res==true){another_function} "
and on this call :
passing_functions("load_database");
I have this string:
res = load_database();if (res==true){another_function}
Ok, I'm unable to use it inside settimetout
settimeout(function() {my_funtion},100}
settimeout(function() {my_funtion()},100}
settimeout(eval(my_funtion),100}
settimeout(my_funtion),100}
settimeout(my_funtion()),100}
etc ---
I have always an error or nothing....
Also I have tried to use "this." as prefix for "thefunction" without success.
Could anybody help me ? What I'm doing wrong ?
Thanks
NOTE:
(I want to create an array of things to be executed.
I could use passing_functions(load_database); but then I receive all the code instead the function. This is because by now I'm using string to pass the code.
)
All your "function calls" end with a } instead of a ) or have the closing ) somewhere in between. The signature is setTimeout(func, time), i.e. the function accepts two arguments, another function and a number. The arguments are put between the (...) and separated by commas. Assuming that my_funtion is actually a function, setTimeout(my_funtion, 100) will be valid.
However it seems you are trying to run JavaScript code that is inside a string. Don't do that. JavaScript is a powerful language where functions are first class citizens. So instead of passing the name of the function and build a string, just pass the function directly:
function passing_functions(thefunction) {
setTimeout(
function() { // first argument: a function
var res = thefunction(); // call the function passed as argument
if (res) {
// I assume you actually want to *call* that function
// just putting another_function there doesn't do anything
another_function();
}
},
100 // second argument: the delay
);
}
// the function load_database must exist at the time you pass it
passing_functions(load_database);
Whether or not this is what you want I cannot say, but it should give you an idea how to properly solve your issue.

getting the name of a variable through an anonymous function

Is it possible to find the name of an anonymous function?
e.g. trying to find a way to alert either anonyFu or findMe in this code http://jsfiddle.net/L5F5N/1/
function namedFu(){
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var anonyFu = function() {
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var findMe= function(){
namedFu();
anonyFu();
}
findMe();
This is for some internal testing, so it doesn't need to be cross-browser. In fact, I'd be happy even if I had to install a plugin.
You can identify any property of a function from inside it, programmatically, even an unnamed anonymous function, by using arguments.callee. So you can identify the function with this simple trick:
Whenever you're making a function, assign it some property that you can use to identify it later.
For example, always make a property called id:
var fubar = function() {
this.id = "fubar";
//the stuff the function normally does, here
console.log(arguments.callee.id);
}
arguments.callee is the function, itself, so any property of that function can be accessed like id above, even one you assign yourself.
Callee is officially deprecated, but still works in almost all browsers, and there are certain circumstances in which there is still no substitute. You just can't use it in "strict mode".
You can alternatively, of course, name the anonymous function, like:
var fubar = function foobar() {
//the stuff the function normally does, here
console.log(arguments.callee.name);
}
But that's less elegant, obviously, since you can't (in this case) name it fubar in both spots; I had to make the actual name foobar.
If all of your functions have comments describing them, you can even grab that, like this:
var fubar = function() {
/*
fubar is effed up beyond all recognition
this returns some value or other that is described here
*/
//the stuff the function normally does, here
console.log(arguments.callee.toString().substr(0, 128);
}
Note that you can also use argument.callee.caller to access the function that called the current function. This lets you access the name (or properties, like id or the comment in the text) of the function from outside of it.
The reason you would do this is that you want to find out what called the function in question. This is a likely reason for you to be wanting to find this info programmatically, in the first place.
So if one of the fubar() examples above called this following function:
var kludge = function() {
console.log(arguments.callee.caller.id); // return "fubar" with the first version above
console.log(arguments.callee.caller.name); // return "foobar" in the second version above
console.log(arguments.callee.caller.toString().substr(0, 128);
/* that last one would return the first 128 characters in the third example,
which would happen to include the name in the comment.
Obviously, this is to be used only in a desperate case,
as it doesn't give you a concise value you can count on using)
*/
}
Doubt it's possible the way you've got it. For starters, if you added a line
var referenceFu = anonyFu;
which of those names would you expect to be able to log? They're both just references.
However – assuming you have the ability to change the code – this is valid javascript:
var anonyFu = function notActuallyAnonymous() {
console.log(arguments.callee.name);
}
which would log "notActuallyAnonymous". So you could just add names to all the anonymous functions you're interested in checking, without breaking your code.
Not sure that's helpful, but it's all I got.
I will add that if you know in which object that function is then you can add code - to that object or generally to objects prototype - that will get a key name basing on value.
Object.prototype.getKeyByValue = function( value ) {
for( var prop in this ) {
if( this.hasOwnProperty( prop ) ) {
if( this[ prop ] === value )
return prop;
}
}
}
And then you can use
THAT.getKeyByValue(arguments.callee.caller);
Used this approach once for debugging with performance testing involved in project where most of functions are in one object.
Didn't want to name all functions nor double names in code by any other mean, needed to calculate time of each function running - so did this plus pushing times on stack on function start and popping on end.
Why? To add very little code to each function and same for each of them to make measurements and calls list on console. It's temporary ofc.
THAT._TT = [];
THAT._TS = function () {
THAT._TT.push(performance.now());
}
THAT._TE = function () {
var tt = performance.now() - THAT._TT.pop();
var txt = THAT.getKeyByValue(arguments.callee.caller);
console.log('['+tt+'] -> '+txt);
};
THAT.some_function = function (x,y,z) {
THAT._TS();
// ... normal function job
THAT._TE();
}
THAT.some_other_function = function (a,b,c) {
THAT._TS();
// ... normal function job
THAT._TE();
}
Not very useful but maybe it will help someone with similar problem in similar circumstances.
arguments.callee it's deprecated, as MDN states:
You should avoid using arguments.callee() and just give every function
(expression) a name.
In other words:
[1,2,3].forEach(function foo() {
// you can call `foo` here for recursion
})
If what you want is to have a name for an anonymous function assigned to a variable, let's say you're debugging your code and you want to track the name of this function, then you can just name it twice, this is a common pattern:
var foo = function foo() { ... }
Except the evaling case specified in the MDN docs, I can't think of any other case where you'd want to use arguments.callee.
No. By definition, an anonymous function has no name. Yet, if you wanted to ask for function expressions: Yes, you can name them.
And no, it is not possible to get the name of a variable (which references the function) during runtime.

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

Javascript Callbacks with custom aguments

I am trying to work out how to implement an asynchronous callback in node given that I don't know what the arguments could be.
I'll state the sync version of what I'm trying to do so as to make this clearer.
function isAuthorized(userID){
// check for user Permissions here
return isAuthorized;
}
Using this any function can call it and, from the value it returns, determine if the user is authorized. However, the function that I use to get the userID (and check for permissions) are both asyncronous functions and require callbacks. However I have no idea how to get this implemented when I don't know the arguments needed in the callback.
The function that calls this could want to send an number of arguments to the callback (normally it'd just wait for a return in sync) and that's what's confusing me.
function isAuthorized(socket, callback, args){
socket.get('userID', function (err, userID) {
//check userID for permission
callback(args);
});
}
I realize I could convert the arguments into an array and send that array, but I wanted to know if there is a more general way to do this that doesn't force me to make all my callbacks convert from an array of arguments.
Hope you can help,
Pluckerpluck
You can always create a function to pull those arguments into an array for you, and then reuse it in each of your async functions:
function asyncWithCallbackArgs(obj, callback) {
var args = Array.prototype.slice.call(arguments, 2);
callback.apply(obj, args);
}
This will then enable you to do things like this:
function callback (c, d, e, f) {
console.log([c, d, e, f]);
}
asyncWithCallbackArgs({}, callback,'c','d','e','f');​
There's a fiddle here to play with.
I'm not sure, if I understand you the right way, but it seems you're looking for the arguments object in a function (MDN link).
Basically that way you don't have to specify any parameters in advance, but have the function look for what parameters are present. So you can do something like the following:
function myFunc() {
for (var i=0; i<arguments.length; ++i ) {
console.log( arguments[i] );
}
}
Which results in outputs like
myFunc( 1 );
> 1
myFunc( 's', 3, 'S' );
> "s"
> 3
> "S"
So when you build an API, you specify what order the arguments are passed into the callback. So, you will want to comment your code well so that anyone who uses your API can understand what they will be getting back from your method.
It almost sounds like you are perhaps wanting to pass back different arguments, depending on what the passed in callback function looks like. That isn't traditionally how an API works. It would take a considerable amount of time to do that effectively.
I would recommend passing an object to the callback. The Object can have multiple arguments that people can pull out of it. This would ease future enhancement, as you could very simply add an additional property to that object without messing up everyone's implementation of your method. So, return something like this :
{
"id": "Some_ID",
"message": "Some Message",
"isAuthorized" : true
}
This way anyone who uses your API doesn't have to account for multiple arguments in the callback method. They know that they are only going to get one arg, and that it will be an Obj with multiple properties, and they can consume which properties they want. Further, in the future you can add a 4th or 5th property without breaking their code. You could add a "datetime" property, and their code would remain unchanged. You would get backwards compatibility, and new implementors could then use the new properties.
If I'm understanding you correctly, don't pass them as arguments at all:
var a = "something";
var b = "something";
var callback = function(){
// use a and b here
};
isAuthorized(socket, callback);
http://jsfiddle.net/S4tH6/
In Coffee-script you have something called splats.
( socket, callback, args... )->
callback args...
This translates as the following in Javascript:
var __slice = [].slice;
function() {
var args, callback, socket;
socket = arguments[0], callback = arguments[1], args = 3 <= arguments.length ?__slice.call(arguments, 2) : [];
return callback.apply(null, args);
};

Categories