Explanation of Following Javascript Code - javascript

I am fairly new to js and I have been looking at the Mozilla Developer site. Under the functions section, I can't seem to grasp the following
function map(f,a) {
var result = [], // Create a new Array
i;
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
particulary, this line "result[i] = f(a[i]);"
From Mozilla:
Function expressions are convenient when passing a function as an argument to another function. The following example shows a map function being defined and then called with an anonymous function as its first parameter
Can you help explain this?
Here is a link for reference.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions

this piece of code applies to every element of array "a" function "f" and returns the array "result" which contains the results of running function "f" for every element in "a".
Sorry, I've got a recursion :)
Actually it can be used like that:
var array = map(function(val){ return val + 1; },[1,2,3,4,5]);
and in "array" you will have these values:
[2,3,4,5,6]

result[i] = f(a[i]);
result is an array and the element at index i is being assigned the result of a function call which takes the parameter a[i].
f in the line above is an anonymous function which is parsed into the map function as the first argument. f would be defined somewhere else in code with the following syntax
function(value) {
return result.
}
The calling code of your example above would look something like.
var array = map(function(value) { return result; },[1,2,3,4,5]);
I would read up on anonymous functions here which might help.
http://en.wikibooks.org/wiki/JavaScript/Anonymous_Functions

Related

How to use apply with currying?

I have code that is using currying to get the average on an array that results from concatenating two arrays: an n size array and an m size array.
var avg = function(...n){
let tot=0;
for(let i=0; i<n.length; i++){
tot += n[i];
}
return tot/n.length;
};
var spiceUp = function(fn, ...n){
return function(...m){
return fn.apply(this, n.concat(m));
}
};
var doAvg = spiceUp(avg, 1,2,3);
console.log(doAvg(4,5,6));
In this line return fn.apply(this, n.concat(m));, I don't understand why do we need to use apply. What is the object we are binding with the average function and why does just normal calling (return fn(n.concat(m));) not work?
In that example, this is not that important. It would also work if instead of this you would pass an empty object instead. It's just an example on how to use apply.
What you need to focus is on the second parameter n.concat(m). They key concept here is that passing an array as a second argument you are calling that function (fn) passing each value in the array as an argument.
About your second question: no, it won't work because fn expects several arguments (one per value to calculate the average) while by doing return fn(n.concat(m)); you are just passing one argument, an array containing all values
Maybe you would understand it better with a simpler example:
function sum3params(a,b,c){
return a+b+c;
}
console.log(sum3params([3,4,2])) // won't work
console.log(sum3params.apply(this, [3,4,2])) // will work ('this' is not important here)
For this use case, it does not. But consider the following:
var foo = {
bar: 3
};
var addBar = function(a, b) { return a + b + this.bar };
foo.add3AndBar = spiceUp(addBar, 3);
foo.add3AndBar(1); // 7
Using apply means that your spiceUp function can be applied to methods as well as normal functions. For more likely example, consider partially applying when defining a method on a prototype:
const ENV = "linux";
DoesSomePlatformSpecificStuff.prototype.getPath = spiceUp(ENV);
apply also will spread the gathered array of arguments back out into positional arguments which can also be done like so:
return fn(...n.concat(m));
Which can be simplified as
return fn(...n, ...m);
Which is equivalent to
return fn.apply(undefined, n.concat(m));

How String.concat() implements in javascript?

In function .concat(), I can pass an arbitrary number of arguments to it.
I understand function overloading in C++, but I don't know how implement a function with unknown number of arguments in JavaScript.
How do I implement an arbitrary number of arguments to a function?
In javascript, you would use the built in parameter called "arguments" which is an array of all the arguments passed to the function. You can obtain it's length with arguments.length and each value from the array arguments[0], arguments[1], etc... Every function has this built in variable that you can use.
For example, a function to concatenate all strings passed to it.
function concatAll() {
var str;
for (var i = 0 ; i < arguments.length; i++) {
str += arguments[i];
}
return(str);
}
var f = concatAll("abc", "def", "ghi"); // "abcdefghi"
You can do this using the arguments object. See the examples and documentation here: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments
Like this -
function f()
{
var i;
for(i=0; i<arguments.length; i++)
{
alert( (i+1) + "th argument: " + arguments[i]);
}
}
All the functions in javascript has a built-in parameter called arguments which is an array containing all the function arguments passed to the function. Just iterate over this array and you will be able to access all the arguments of a function.
As an example, once I've written a function which is used to enable/disable certain button if some specific fields were not empty. I wrote this function this way -
function toggleButton() // I used jquery inside this function
{
var i;
var last = arguments.length-1;
for(i=0; i<last; i++)
{
if( $.trim($(arguments[i]).val()) === "" )
return false;
}
$(arguments[last]).toggle();
return true;
}
and called this function like this -
toggleButton("#idOfFirstField", "#idOfSecondField", "#idOfButtonToToggle");
or like this -
toggleButton("#idOfFirstField", "#idOfSecondField", "#idOfThirdField", "#idOfButtonToToggle");
so in both the cases, I was passing variable number of field ids to the function and it checked that if these fields were empty. If all of them contained some value, then it toggled the visibility of the button.
Like this - use the arguments object all functions have available :
function someFunction() {
for (var i=0,n=arguments.length;i<n;i++) {
// do something with arguments[i];
}
}
You can use the arguments array to access parameters that are not formally declared inside the function:
function printArguments() {
for (i = 0; i < printArguments.arguments.length; i++)
document.writeln(printArguments.arguments[i] + '<br />');
}
printArguments(1, 2, 3, 'etc');
Source: http://www.irt.org/articles/js008/
Any javascript function can have an arbitrary number of arguments. If function execution depends on the number or specific qualities of it's arguments, you'll have to check the arguments object, which can be iterated like an 'Arraylike' object, as others have shown.
In some cases it may be handy to convert the arguments to a real array, using something like
var args = Array.prototoype.slice(arguments).
Here's a blog entry from John Resigs page on method overloading that may interest you.

Object inside of array -- works in one scope but not in another?

Ok I've been learning some of the more advanced aspects of Javascript and now trying to use this I'm stuck.
Here is my code:
function Data(){}
function init(state){
var item;
item=new Data();
item.fieldrid=17;
item.description='foo';
state.push(item);
};
function findInState(state,fieldrid) {
for (var item in state) {
alert(item.fieldrid); //prints undefined
if (item.fieldrid == fieldrid) {
return item;
}
}
return null;
}
var s=[];
init(s);
alert(s[0].fieldrid); //prints 17 (expected)
alert(findInState(s,17).fieldrid); //exception here. function returns null.
A running example is here at jsbin
Why does this not work? I would expect the alert in findInState to yield 17 but instead it yields undefined.
What am I doing wrong?
for (var item in state)
You should not loop over an array using for..in.
It works as expected when using for (var i = 0; i < state.length; i++).
See https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for...in:
Although it may be tempting to use this as a way to iterate over an Array, this is a bad idea.
In
alert(item.fieldrid); //prints undefined
You need to access the array state[item] so before that line, prepend
item = state[item];
I think, that I'll do.

Using a variable as identifier in a json array

I'm wondering if it is possible to use assigned variables as identifier in a json array. When I tried this, I was getting some unexpected results:
(Code is simplified, parameters are passed in a different way)
var parameter = 'animal';
var value = 'pony';
Util.urlAppendParameters(url, {
parameter: value
});
Util.urlAppendParameters = function(url, parameters) {
for (var x in parameters) {
alert(x);
}
}
Now the alert popup says: 'parameter' instead of 'animal'. I know I could use a different method (creating an array and assigning every parameter on a new line), but I want to keep my code compact.
So my question is: Is it possible to use a variable as an identifier in the json array, and if so, could you please tell me how?
Thanks in advance!
You will need to build your object in two steps, and use the [] property accessor:
var parameter = 'animal';
var value = 'pony';
var obj = {};
obj[parameter] = value;
Util.urlAppendParameters (url, obj);
I don't think JSON Array is the more correct term, I would call it Object literal.
No, you can't use a variable as an identifier within an object literal like that. The parser is expecting a name there so you can't do much else but provide a string. Similarly you couldn't do something like this:
var parameter = 'animal';
var parameter = 'value'; //<- Parser expects a name, nothing more, so original parameter will not be used as name
The only work around if you really really want to use an object literal on a single line is to use eval:
Util.urlAppendParameters (url, eval("({" + parameter + " : value})");
Depending on your needs you could also build your object with a helper function;
Util.createParameters = function(args) {
var O = {};
for (var i = 0; i < arguments.length; i += 2)
O[arguments[i]] = arguments[i + 1];
return O
}
Util.urlAppendParameters (url, Util.createParameters(parameter, value, "p2", "v2"));

What is this javascript code doing?

this.String = {
Get : function (val) {
return function() {
return val;
}
}
};
What is the ':' doing?
this.String = {} specifies an object. Get is a property of that object. In javascript, object properties and their values are separated by a colon ':'.
So, per the example, you would call the function like this
this.String.Get('some string');
More examples:
var foo = {
bar : 'foobar',
other : {
a : 'wowza'
}
}
alert(foo.bar); //alerts 'foobar'
alert(foo.other.a) //alerts 'wowza'
Others have already explained what this code does. It creates an object (called this.String) that contains a single function (called Get). I'd like to explain when you could use this function.
This function can be useful in cases where you need a higher order function (that is a function that expects another function as its argument).
Say you have a function that does something to each element of an Array, lets call it map. You could use this function like so:
function inc (x)
{
return x + 1;
}
var arr = [1, 2, 3];
var newArr = arr.map(inc);
What the map function will do, is create a new array containing the values [2, 3, 4]. It will do this by calling the function inc with each element of the array.
Now, if you use this method a lot, you might continuously be calling map with all sorts of arguments:
arr.map(inc); // to increase each element
arr.map(even); // to create a list of booleans (even or odd)
arr.map(toString); // to create a list of strings
If for some reason you'd want to replace the entire array with the same string (but keeping the array of the same size), you could call it like so:
arr.map(this.String.Get("my String"));
This will create a new array of the same size as arr, but just containing the string "my String" over and over again.
Note that in some languages, this function is predefined and called const or constant (since it will always return the same value, each time you call it, no matter what its arguments are).
Now, if you think that this example isn't very useful, I would agree with you. But there are cases, when programming with higher order functions, when this technique is used.
For example, it can be useful if you have a tree you want to 'clear' of its values but keep the structure of the tree. You could do tree.map(this.String.Get("default value")) and get a whole new tree is created that has the exact same shape as the original, but none of its values.
It assigns an object that has a property "Get" to this.String. "Get" is assigned an anonymous function, which will return a function that just returns the argument that was given to the first returning function. Sounds strange, but here is how it can be used:
var ten = this.String["Get"](10)();
ten will then contain a 10. Instead, you could have written the equivalent
var ten = this.String.Get(10)();
// saving the returned function can have more use:
var generatingFunction = this.String.Get("something");
alert(generatingFunction()); // displays "something"
That is, : just assigns some value to a property.
This answer may be a bit superflous since Tom's is a good answer but just to boil it down and be complete:-
this.String = {};
Adds an object to the current object with the property name of String.
var fn = function(val) {
return function() { return(val); }
}
Returns a function from a closure which in turn returns the parameter used in creating the closure. Hence:-
var fnInner = fn("Hello World!");
alert(fnInner()); // Displays Hello World!
In combination then:-
this.String = { Get: function(val) {
return function() { return(val); }
}
Adds an object to the current object with the property name of String that has a method called Get that returns a function from a closure which in turn returns the parameter used in creating the closure.
var fnInner = this.String.Get("Yasso!");
alert(fnInner()); //displays Yasso!

Categories

Resources