How can a parameter exist when no argument is passed? - javascript

I'm new to Javascript, although I have a .net background. Typically in .NET (as well as many other languages), if a method requires a parameter to be passed, you have to pass it (or else compiler error due to incorrect signature). This also appears to be the case in JavaScript, but not all cases it would appear.
This doesn't appear to be the case in Javascript.
As a working example, please refer to line 61
http://www.humblesoftware.com/flotr2/#!basic-axis
Line 61 is tickFormatter: ticksFn,
I understand that tickFormatter is calling a function called ticksFn but line 29 shows
function ticksFn(n) {
return '(' + n + ')';
}
'ticksFn' requires a value (n) to be passed, yet, we never pass it.
Despite that, javascript still gets it right and I can't find out how, nor can I work/understand what to search for to do more research

You never call it at all. You pass the function itself as an argument (or rather as the value of a property of an object that is an argument).
graph = Flotr.draw(container, [ /* ... */], {
xaxis : {
noTicks : 7, // Display 7 ticks.
tickFormatter : ticksFn, // Displays tick values between brackets.
// …
Your third party library code is responsible for actually calling that function, and it does so with an argument.

In javascript it is not required to pass the parameters for a function as a value of undefined is passed if you don't.
So a function:
function ticksFn(n) {
return '(' + n + ')';
}
Can be invoked:
ticksFn();
Without any problem and the value of the n will be undefined..
Alternatively a function defined with no arguments:
function ticksFn() {
return '(' + arguments[0] + ')';
}
And calling:
ticksFn(10);
arguments[0] will be 10. and accordingly you can read any number of arguments.
That was a quick tutorial about javascript functions.. now about your code.. javascript is a function oriented language and so writing the function name without parentheses actually hands reference on the function rather than calling the function itself..

Related

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

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.

Is there a way to do variadic recursive currying in Javascript?

I know that there probably wouldn't be any reason to use this over some other way of creating a variadic function, but is it semantically possible to define something to do this? For example, it could be called like sum(1)(2)(3)();. I attempted to implement it with the following code:
function sum(x) {
return function(y) {
if (!y) return 0;
else return x + sum(y);
};
}
However, when called this gives TypeError: string is not a function. What would cause this to return a string? When I inspected it more closely, it looked like it was returning the code for the function as a string, which makes no sense to me. That said, I am not extensively familiar with the semantics of intricate JavaScript, so I could be missing some huge concept in it.
As mentioned in the comments, x is a number and sum(y) is a function. Using the + operator on them uses their gcd type which are strings, and cannot be called.
You cannot curry operators in javascript. You need to return a curried function explicitly, and tell it when to calculate the values. An appropriate fix for our function would be
function sum(x) {
return function(y) {
if (!y) return x;
// ^
else return sum(x + y);
// ^^^
};
}
sum(1) -> ref Function(y)
sum(1)(2) -> invocation Function(2)
Function(2) -> 1 + (sum(y) -> sum(2) -> ref Function(y))
Now, 1 + (ref Function(y)), as you can see, you're adding a number and a reference.
The javascript is thinking that you're trying to concatenate, hence it calls ToString method of Function, internally, which gives the function body as a string.
So, the next time you call, you're calling on a String and hence the error as String isn't a function.
A correct code would be what Bergi has implemented.

Can I detect unused extra parameters passed to javascript methods?

In Javascript I can call any method with more than the necessary amount of parameters and the extra parameters are silently ignored.
e.g.
letters = ['a','b','c']
//correct
letters.indexOf('a')
//This also works without error or warning
letters.indexOf('a', "blah", "ignore me", 38)
Are there ways to detect cases where this occurs?
My motivation is that in my experience cases where this occurs are usually bugs. Identification of these by code analysis or at runtime would help track these errors down.
These cases are especially prevalent where people are expecting alterations to base types which may not have occurred. Logging a warning where this happens
e.g.
Date.parse('02--12--2012', 'dd--MM--YYYY')
Notes:
To be clear I would like a solution that doesn't involve me sprinkling checks all over my code and other peoples' code.
You can use the arguments object.
function myFunction(param1,param2)
{
if (arguments.length!=2)
{
// wrong param number!
}
...
}
As per your edit: If you want to implement an automated form of check, without ever touching the original functions:
You still have to process each function with:
functionName = debug(functionName, numberOfExpectedArgs);
This operation wraps the function with a check of the number of arguments.
So we leave a sample function untouched:
// this is the original function... we want to implement argument number
// checking without insertint ANY debug code and ANY modification
function myFunction(a,b,c)
{
return a + " " + b + " " + c;
}
// the only addition is to do this...
myFunction = debug(myFunction,3); // <- implement arg number check on myFunction for 3 args
// let's test it...
console.log(myFunction(1,2,3));
console.log(myFunction(1,2));
You need to implement this debug() function:
function debug(f, n)
{
var f2 = f;
var fn = function()
{
if (arguments.length!=n) console.log("WARNING, wrong argument number");
return f2.apply(f2, arguments);
};
return fn;
}
​
This solution is TOTALLY transparent as per already defined functions, so it may be what you seek for.
I strongly suggest to check against deprecations (there are some) and crossbrowser compatibility.
The functions in JavaScript are objects. As such they have properties. What you want can be achieved with length MDN property, which specifies the number of arguments expected by the function.
function say ( hello, world ) {
alert (
"arguments length = " + arguments.length + "\n" +
"defined with = " + say.length
);
}
say ( "this ", "brave ", "new ", "world" );​
This works even on IE8. Demo. In your case you can do something like this.
Javascript is a very dynamic language and many of its useful features also make it impossible to do some checks statically.
The existance of the arguments implicit object means there is no way to automatically determine how many arguments a function is expecting for all functions. Many var-arg functions declare no formal arguments and uses the arguments object exclusively.
All you can reliably do is to check it manually in each function like Cranio suggested.
If you want to have automated checks, e.g. as part of your unit tests, you can make use of the length property of the Function objects, which returns the number of formal arguments. For var-arg functions, just don't include the check. For example:
function checkNumberOfArguments(args) {
if (args.length != args.callee.length) {
throw new Error('Wrong number of arguments');
}
};
// Use it like
function a(b) {
checkNumberOfArguments(arguments);
}
a(1);
a(1,2);
Inside function you can use arguments object, it contains an array of all the arguments that were supplied to the function when it was called.
function x(){
return arguments.length;
}
x()
=> 0
x(1,1,1,1,1,1,1,1,1)
=> 9

Evaluating JSON strings - eval() vs. new Function() [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
jQuery uses (new Function(“return ” + data))(); instead of eval(data); to parse JSON, why?
Given a string which represents a valid JSON string, is there a difference between these two parsing methods:
var str, obj;
str = '{"prop":"value"}';
// method 1:
obj = eval( '(' + str + ')' );
// method 2:
obj = ( new Function( 'return (' + str + ');' ) )();
I noticed that jQuery uses the second method to parse JSON strings (in environments that lack a built-in JSON parser). I wonder why they don't use the first method. Why create a function object and invoke it when you can just use eval()?
Please close as exact duplicate
eval is executed within the scope it was declared. Function generates a new function object with its own scope and returns a reference to that function which can be called.
Take this example:
var x = 123;
var y;
function TestEval()
{
var y = 1;
Function("window.alert('Global x: ' + x);")(); //Prints 123
Function("window.alert('Local y: ' + y);")(); //Prints undefined
eval("window.alert('Global x: ' + x);"); //Prints 123
eval("window.alert('Local y: ' + y);"); //Prints 1
}
TestEval();
The first two Function calls will print 123 (the global value of x) and undefined, the global value of y.
The two eval functions will print 123 and 1 (the local value of y). This is because eval has local access to the closure it's being run within. These behaviors (as well as the fact that eval is completely unreliable and inconsistent across many browsers) could be taken advantage of by the jQuery implementation.
Note: Code above tested in Firefox 8, your mileage may vary :)
Using eval is evil because there can be lots of security holes. You are executing code in global scope. Function takes of this differently by executing in its own scope. But one thing Function does better is performance. Looking at this blog shows that Function is almost 2x faster in FF2.
Edit: I am not sure how much more secure it is when you execute document.location = "bad-url", it would still be executed using Function
The global scope thing and also it won't execute anything after a ";" because of the return, that helps a lil bit.

Passing unknown amounts of variables using through a string string and eval and multiple functions and all sorts

In short, I want to use an object literal to allow me to pass a unknown amount of variables in any order to a function. Whilst this is not big deal in theory, in my code, this object literal is passed to a second function called on_change.
on_change works by comparing an element's innerHTML to a string; If it is the same, it sets a timeout to call the function again. If the element's innerHTML is different from the string, then the third parameter is executed, this will either be a function or a string. either way it will execute. I have tested this function plenty and used it for a while now.
However, I cannot seem to get the object literal to flow through the function calls...
var params = { xpos:'false'};
on_change('window_3_cont_buffer','','
if(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[0].innerHTML == \'ERROR\'){
alert(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[1].innerHTML);
return false;
} else {
Window_manager.windows[3].load_xml(\'location/view.php?location_ID=3\', \'\', ' + params + ' ); }
');
I call this as part of the form submission. After this line, I then call a function to load some content via ajax, which works fine and will trigger the code from the on_change function.
I have tested the load_xml function, it is able to call alert(param.xpos) and get the correct response. I can even added in a check for being undefined so that rest of the times I call load_xml I don't get swamped with alerts.
The load_xml function first sets up the on_change function, then calls the function to load the content to a hidden div. Once the AJAX request has updated that DIV, the on_change function should now call the parse_xml function. This pulls out the information from the xml file. However... The idea of this object literal param is that it can tell this parse_xml function to ignore certain things.
on_change("window_" + this.id + "_cont_buffer", "", "Window_manager.windows[" + this.id + "].parse_xml('" + param + "')");
This is part of load_xml, it works perfectly fine, even with the param bit in there. except, parse_xml does not seem to be able to use that parameter.
I have been able to get it to a point where parse_xml can alert(param) and give [object object] which I would of thought meant that the object literal had been passed through, but when I try and call alert(param.xpos) I get undefined.
I know this is a pig of a problem, and I could get around it by just having the function take a zillion boolean parameters, but its just not a very nice solution.
In effect, what you have is this:
var params = {param: "value"};
foo("bar('one', 'two', 'three');");
...where foo uses eval on that string, something like:
function foo(codestring) {
eval(codestring);
}
...and you're looking for how to embed params in that.
You could do this by serializing the object literal as a string so that when you combine it with the other string, and the total string is evaluated, it gets evaluated. Browsers are slowly getting JSON serialization built in, but for now you want to use jQuery, Prototype, or (if you just want this part) json2.js from Crockford, which offers JSON.stringify for turning objects that can be turned into JSON strings, into JSON strings. So:
var params = {param: "value"};
foo("bar(" + JSON.stringify(params) + ");");
But what you really want to do is refactor so that all of that logic is expressed as code, not code within a string. Then you could pass the literal directly, plus a whole raft of other benefits, including modularization, debugging, etc.
var params = {param: "value"};
function callBar() {
bar(params);
}
foo(callBar);
...changing foo so that it calls a function rather than evaling a string. (eval is to be avoided whenever possible, and to paraphrase the Dalai Lama, it's [almost] always possible.) My sample foo changes to:
function foo(func) {
func();
}
If foo needs to include additional information for bar (and if callBar is set up to handle those extra arguments), it can use Function#call or Function#apply to do that. (Those links are to MDC, but don't worry, they're not Firefox-specific, they've been in the ECMA spec for years and are nearly universally supported.)
You can't put an object inside a string. You would have to serialise the object, add it into the string, then parse it back into a structured object on the other side. The simplest way to do that would be to use JSON (via JSON.stringify or a library fallback for older browsers that don't have it), since JSON evaluates as simple JavaScript.
Note that you wouldn't get the exact same object back, but a new one with the same attributes and properties, and it only works for simple types, so you can't include a function in the object or anything.
However, in any case, passing JavaScript code around in strings is an anti-pattern to be strenuously avoided. Instead use inline functions, and you don't have to worry about what you can and can't put in a string, and you can get rid of all that unreadable wrapping and \-escaping:
var params = {xpos: 'false'};
on_change('window_3_cont_buffer', '', function() {
var w= Window_manager.windows[3];
var ps= w.window_cont_buffer.getElementsByTagName('content')[0].getElementsByTagName('p');
if (ps[0].innerHTML==='ERROR') {
alert(ps[1].innerHTML);
return false;
} else {
w.load_xml('location/view.php?location_ID=3', '', params);
}
});
Some general techniques which may be helpful for you:
// Example of calling function objects given as arguments:
function on_change(foo, callback1, callback2) {
if (foo)
callback1();
else
callback2.call(available_as_this);
}
on_change(foo, function() { your code }, function() { another code });
// Example of function taking arbitrary number of arguments:
function any_params() {
console.log('I got ' + arguments.length + 'arguments!');
console.log('First argument: ' + arguments[0]);
}
any_params('one', 'two', 'three', [], null, {});
See arguments variable and call().
I want to use object literal to allow me to pass a random amount of variables in any order to a function.
Why oh why don't you just create an object which contains the parameters and functions, and pass that around? The receiving function can just test to see if a property of the object is set before trying to use it.

Categories