Understanding the terms iteratee, callback, function factory in JavaScript - javascript

I am trying to become a little bit familiar with the JavaScript terminology. I think I am confused with the terms iteratee, callback and function factory
Let me use the following silly example:
//this function accept an array and then returns a new array that
//contains the elements of the first array altered by func
function mapForEach(arr, func) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
newArr.push(func(arr[i]));
}
return newArr;
}
//this function multiplies two numbers
var multiply = function (a, b) {
console.log(a * b);
};
//this is a silly function that passes a multiplier as the first
//argument of the multiply function
var multiplyBy = function(multiplier) {
return multiply.bind(this, multiplier);
};
var arr = [1, 2, 3];
mapForEach(arr, multiplyBy(3)); //[6, 10, 20]
So, to my understanding thus far:
iteratee (aka predicate) is a function object that does some work. In this example mapForEach accept a func object to do some work with the arr elements, so func can be called iteratee and hence multiplyBy is an iteratee. In a general concept maybe multiply can also be considered an iteratee as is a standalone function that performs a basic work.
callback is a function A you give to another function B to be invoked by the other function (so, the other function B --sort to speak-- "calls back" the function A). In this example when mapForEach is called, is executed in a new environment where it calls back the func function object. So the func object can also be called a callback. However, in the same context, mapForEach can also be considered as a function that, when is executed, calls back the multiplyBy function, i.e. multiplyBy is a callback too.
function factory we call a function that does some work for us and/or return a value (i.e an array, object, function object, whatever....). In our example multiplyBy is a function object that when it is called it returns (a copy of) another function object (multiply) that has the multiplier parameter in its closure. Thus multiplyBy is a factory function.
Am I getting all these right, (or am I going insane :-P)

Iteratee is not a function that just does some work. It has to do some work on an iterable set, an array for example. A predicate is a function that takes an argument and returns true/false, predicates are for example used for filtering iterable sets. Thus, iteratee and predicate are definitely not the same.
Function factory is not just a function that does some work and returns a value. It is a function that is capable of creating a family of other functions based on supplied arguments.
The multiplyBy is not a callback "per se", the func passed to mapForEach is. The multiplyBy becomes a callback when you pass it to another method that calls it back.

Related

Js currying with condition

im trying to understand this code for long time i know currying function but confused with this code please explain theory behind
var currying = function(fn) {
var args = [];
return function() {
if (!!arguments.length){
[].push.apply(args, arguments);
return arguments.callee;
} else {
// what is 'this' in apply method
return fn.apply(this, args);
}
}
}
// currying var or args
// please explain the code below
var find = function(arr, el){
return arr.indexOf(el) !== -1;
}
var newFind = currying(find)([1,2,3]);
console.log( newFind(1)());
console.log( newFind(2)());
To make it easier to explain, let's convert the last part of the code:
// newFind = currying(find)([1,2,3]);
// console.log(newFind(1)());
// above is the same with below
console.log( currying(find)([1,2,3])(1)());
currying takes a function find so fn in currying is find.
As it return a function, it can be called as it's shown on the code currying(find)([1,2,3])
let's look at this part, currying(find)([1,2,3]).
It executes the returned method of currying. It can access the arguments with keyword arguments that is the array of [1,2,3] on the code.
The argument is the array which means it has the length value. Then the arguments is pushed into args array and return its callee which means inner method of currying.
As it returns method again, it can be called again with next paramter (1) of currying(find)([1,2,3])(1)().
Again, it executes the inner method of currying with arguments: 1. Then it is not an array so, it calls fn.apply(this, args).
this keyword in the code means nothing in this case. you can replace this to null or you can use fn(...args) instead. the code is for converting array of argumnts to each argument. e.g. [[1,2,3], 1] is converted to [1,2,3], 1
Then, finally it executes find function with parameter [1,2,3], 1. You should remember all this thing is from returned method of currying so, you must call it as a function. append () at the end to execute the function.

Why don't I pass any parameters to a function within map?

How come we do not have to pass an argument to function b
in the code below? Is it just because we are using map method of type Array? Or is there anywhere else that we can use a function just like this in
JavaScript?
Can someone give a very clean and through explanation?
Code:
/* we have an array a*/
const a = ['a', 'b', 'c'];
/*we define a function called b to process a single element*/
const b = function(x){do something here};
/*I noticed that if we want to use function b to take care with the
elements in array a. we just need to do the following.*/
a.map(b);
Functions are first class citizens in Javascript, which is just a fancy way of saying they can be passed around as variables and arguments.
What you are doing when you call
a.map(b);
Is essentially calling
[
b('a'),
b('b'),
b('c')
]
The array function map just calls the given function (in your case b), with each argument in the array, and puts the output in a new array. So there are arguments being passed to b, it's just that map is doing it behind the scenes for you.
As for your other questions, there are plenty of cases where you'll pass a function as an argument without calling it first. Another common function is the Array object's reduce.
const out = a.reduce(function (accumulator, val) {
return accumulator + ' - ' + val;
}
// out: 'a - b - c'
Also a lot of functions take callbacks, that are called when some kind of asynchronous task is completed. For instance. setTimeout, will call a given function after the elapsed time.
setTimeout(function (){
console.log("Hello World!");
}, 1000
);
// Will print "Hello World!" to console after waiting 1 second (1000 milliseconds).
And you can easily write your function to take another function as an argument too! Just call the function you've passed in as you would any other function.
// A really basic example
// More or less the same as [0, 1, 2].map(...)
function callThreeTimes(f) {
return [
f(0),
f(1),
f(2)
]
}
// My function here returns the square of a given value
function square(val) { return val * val }
const out = callThreeTimes(square);
// out: [0, 1, 4]
You don't pass arguments to b because you're not calling it. You're passing the function itself as a value.
The use of map here is irrelevant; you can see what's happening directly:
const a = function(x) { alert(`called with ${x}`); };
// The function is NOT called here; it's just being assigned,
// like any other kind of value. This causes "b" to become
// another name for "a".
// This is NOT the same as a(), which would call the function
// with undefined as the argument.
const b = a;
// Now we call it, and the alert happens here
b(5);
Passing a function to another function works the same way, since it's just another form of assignment.
This is useful because you can tell other code how to do something even if you yourself don't know what the arguments are. In the particular case of map, it loops over the array for you and calls the function once for each element. You don't want to be calling the function you pass to map, because the entire purpose of map is to call the function for you.
map accepts function as a parameter and executes provided function for every element of an array.
Here you are passing function b as a parameter to map, hence map executes function b for every elements of array a.
So you do not need to pass arguments to function b here, map will take care of this.
You probably heard that functions are first class citizens in javascript.
If you look at the docs from MDN map you will notice that the map function accepts a callback with up to 3 arguments first one being currentValue
So let's break it down. A very explicit example of doing a map over the array above would be this one
a.map(function(currentValue, index, array){
// here you can access the 3 parameters from the function declaration
});
This function is called on each iteration of the array. Since functions are very flexible in javascript, you could only declare 1 parameter or even none if you want to.
a.map(function(currentValue){
// we need only the current value
});
Every function in JavaScript is a Function object. Source here
This means that every function is just a reference in the memory, meaning it can be specified either directly as an anonymous function (which is our case above), or declared before like this
function b(currentValue){
// this will be called on each item in the array
};
a.map(b)
This piece of code iterates over each element in the array and calls the reference we passed it (function b). It actually calls it with all the 3 parameters from the documentation.
[
b('a',0,a),
b('b',1,a),
b('c',1,a)
]
But since our function b only declared one, we can access the value only.
The other arguments are stored in the so-called Arguments object
Take from here Every function in JavaScript is a Function object which makes every function a reference to a certain memory location which in the end leaves us with a lot of flexibility of passing the function as a parameter however we want to (explicit via an anonymous function, or implicit via a function declaration (reference) )
how come we do not have to pass argument to function b here?
Simply because as per spec, map calls the b with 3 implicitly.
callbackfn is called with three arguments: the value of the element,
the index of the element, and the object being traversed
For each element in the array, callback function is invoked with these three arguments
value of the element (a, b and c in your case)
index of the element
b itself (object being traversed).
Why there are no parenthesis?
When you are passing a function as an argument to the sort method it doesnt have parentheses after the function name. This is because the function is not supposed to be called right then and there but rather the map method to have a reference to this function so that it can call it as needed while it's trying to map the array.
Why it does not take any arguments?
Now we know that map will be calling this callback function accordingly, so when map calls it it implicitly passes the arguments to it while calling it.
For example if this would be callback of sort then the argument passed will be current element and next element. If this is a callback for map then the arguments will be current value, index, array.
In JavaScript, functions are just another type of object.
Calling a function without arguments is done as follows. This will always execute the function and return the function's return value.
var returnValue = b();
Removing the parenthesis will instead treat the function itself as a variable, that can be passed around in other variables, arguments etc.
var myFunction = b;
At any point such adding parenthesis to the "function variable" will execute the function it refers to and return the return value.
var returnValue = myFunction();
var sameReturnValue = b();
So map() accepts one argument, which is of type function (no parenthesis). It will then call this function (parenthesis) for each element in the array.
Bellow you will find how to use the map function:
first Methode
incrementByOne = function (element) {
return element + 1;
}
myArray = [1,2,3,4];
myArray.map(incrementByOne); // returns [2,3,4,5]
Seconde methode
myArray = [0,1,2,3];
myArray.map(function (element) {
return element + 1;
}); // returns [1,2,3,4]
Third Methode
myArray = [1,2,3,4];
myArray.map(element => {
return element + 1;
});

How do I use the "arguments" key on the function object?

If I type this and check it out in my Chrome console:
function f(){}
console.dir(f);
What is displayed are these keys:
> arguments
> caller
> length
> name
> prototype
> __proto__
Now, I'm curious if the arguments key on the constructor function is there to aid me in some way visually to see the arguments that are passed to a function, but everytime I pass an argument to a function it fires it off automatically:
function f(a){alert(a)}
console.dir(f("test"));
So, it seems quite useless as an analytic tool. Is this key just here to temporarily hold the arguments and nothing more just for the sake of passing arguments? Or is there something else to this key? I'm sure this is probably a dumb question but I'm curious.
The arguments object is a local variable available within all functions.
You can refer to a function's arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function.
if a function is passed three arguments, you can refer to the argument as follows:
arguments[0]
arguments[1]
arguments[2]
Reference link arguments.
arguments is an array like object that is available in function objects in javascript. It allows a function a way to account for arguments that were used while invoking a function but do not have a parameter specifically assigned to it.
var mul = function ( ) {
var i, total = 0;
for (i = 0; i < arguments.length; i += 1) {
total *= arguments[i];
}
return total;
};
document.writeln(mul(4, 8, 2)); //64
Source: http://goo.gl/hKpFGl
This explanation is pretty much ripped directly from here. If you want to get familiar with some good patterns javascript offers this isn't a bad place to start.
arguments is an Array-like object corresponding to the parameters passed to a function.
For Example:
function callMe (a, b, c){
console.log(arguments);
}
callMe(); // return empty array []
callMe(1,2); // return array [1, 2]
callMe(1,2,3); // return empty array [1, 2, 3]
callMe(1,2,3,4); // return empty array [1, 2, 3, 4]
For more help, read this doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments

Function arguments and how they work

I'm just trying to get a better understanding/confirmation of function arguments
In the function seen here:
function newFunction(data, status){
would the function apply specifically to data and status variables?
I don't quite understand how the arguments work.
Basic Scenario
When a function is defined, the () area is used for inputs. These inputs are mapped to what data is sent in.
function newFunction(data, status){
}
newFunction(1,2);
In this scenario, data will be assigned the value of 1, and status will be assigned the value of 2 for the scope of newFunction.
Missmatched inputs
However, it does not always directly map. If fewer arguments are sent, then the unassigned input variables become undefined.
function newFunction(data, status){
}
newFunction(1);
In this scenario, data will be assigned the value of 1, and status will be assigned the value of undefined for the scope of newFunction.
arguments object
Inside of the scope of newFunction, there is also access to the array like object called arguments.
function newFunction(data, status)
{
var args = arguments;
}
newFunction(1);
In this scenario, the variable args will hold the arguments object. There you can check args.length to see that only 1 argument was sent. args[0] will give you that argument value, being 1 in this case.
Function object
A function can be made into an object with the new keyword. By using the new keyword on a function, a Function object is made. Once the Function object is made, this may be used to refer to the current Function object instead of the global window.
function newFunction(data,status){
if( this instanceof newFunction ){
//use as a Function object
this.data = data;
}else{
//use as a normal function
}
}
var myNewFunction = new newFunction(1);
In this scenario, myNewFunction now holds a reference to a Function object, and can be accessed as an object through dot notation or indexing. myNewFunction["data"] and myNewFunction.data now both hold the value of 1.
This means that the function accepts both data and status parameters. The programmer calling the funciton (you) is required for providing the parameters when calling the function (also known as arguments.)
Let's look at a simplified example:
function add(x, y) {
return x + y;
}
The function here takes two numbers, adds them together, and returns the result. Now, as a programmer, you have the benefit of adding two numbers whenever you want without having to duplicate the functionality or copy/paste whenever you need your application to perform the same functionality.
Best of all, another programmer you work with can add two numbers together without worrying about how to do it, they can just call your function.
EDIT: Calling the function works as follows
var num1 = 10;
var num2 = 15;
var z = add(num1, num2); //z = 25
function newFunction(data, status){ ... function code ... }
This is the Javascript definition of a function called newFunction.
You can pass arguments to a function. These are variables, either numbers or strings, with which the function is supposed to do something.
Of course the function behaviour/output depends on the arguments you give it.
http://www.quirksmode.org/js/function.html

Prototype "Bind" method issue

Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
**args.concat(Array.prototype.slice.call(arguments))**);
};
};
This function is in Prototype. Does it equal to:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,**args**);
};
};
In my opinion, args.concat(Array.prototype.slice.call(arguments)) == args, since the anonymous
function haven't any arguments. What is the matter?
No, they aren't the same.
Tthe purpose of concatenating the arguments is to provide a way of partially apply (or curry) the function, pre-filling arguments when bind is used and being able to add more later when the function that bind returns is used, for example:
var obj = {
fx: function() {
alert(Array.prototype.join.call(arguments, ', '));
}
};
var fx2 = obj.fx.bind(obj, 1, 2, 3);
fx2(4, 5); // Alerts "1, 2, 3, 4, 5"
As you can see in the last two lines of code, when I declare fx2, I'm passing obj as the first argument (this will ensure the context, used as the object variable on the bind implementation), then I pass the values 1,2 and 3.
Those values are stored in the args variable of the outer closure of bind, then as you see in the bind implementation, another function is returned.
That function returned in my example is fx2 after the assignment, in the last line you see I call that function, passing two additionally arguments.
Finally the returned function will call obj.fx with the two argument lists, the arguments we pre-filled when calling bind (1,2,3) and the arguments when the function actually executed (4,5).
That is why makes sense concatenating the two argument objects.
the anonymous function haven't any arguments
The anonymous function can actually have arguments (as can the bind method itself, which also doesn't declare any arguments).
Type-checking in JavaScript is non-existent: you can pass fewer arguments into a function than are declared in the function(...) signature (in which case the arguments that aren't passed get received as undefined), and you can pass more than declared, in which case the only way to read them is through the arguments array, which always contains exactly how many arguments were passed in, regardless of what's in the function signature.
It's generally considered polite to put a comment in the signature (function(x, /* y, ... */)) to indicate that more arguments will be read using the arguments array.

Categories