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));
Related
I'm trying to write my own higher order function right now and I want to know how functions like map() and reduce() access the array they are being applied to. And not just for arrays either, but with any higher order function like toString() or toLowerCase().
array.map()
^^^ // How do I get this data when I am writing my own higher order function?
array.myOwnFunction(/* data??? */)
I hope this makes sense. I'm sure the answer is out there already, but I'm struggling to know what to search for to find the information.
You can add it to the Array prototype like :
Array.prototype.myOwnFunction = function() {
for (var i = 0; i < this.length; i++) {
this[i] += 1;
}
return this;
};
const array = [1, 2, 3];
const result = array.myOwnFunction();
console.log(result);
Check the polyfill for Array.prototype.map(), this line in particular:
// 1. Let O be the result of calling ToObject passing the |this|
// value as the argument.
var O = Object(this);
Simplifying, this is where the values are received.
The way this works is related to the prototype and to the "thisBinding".
When a function is instantiated using new, the properties of the prototype are attached to the new Function object. As well, an "execution context" is created to maintain the environment. The properties of the prototype are then accessible in the environment through the current instance's this binding using this.
So if you have a function you want to use the data from in an instance, you can use a prototype as well. For many reasons (memory use, readability, reusability, inheritance, polymorphism, etc.) this is the best way to go about doing it. Modifying standard implementations such as Array, Math, Date, etc. are generally discouraged (although there will always be exceptions).
function LineItem(description,price,quantity){
this.description = description;
this.price = price;
this.quantity = quantity;
}
LineItem.prototype.Total = function(){
return this.price * this.quantity;
};
var avocados = new LineItem("avocado",2.99,3);
console.log(avocados.Total());
The main thing to take away here is that the thisBinding allows access to the current instance's object through this. That is where the data access comes from. For example, in an array instance, this references the current array; in a date instance, this references the current date; in the above LineItem example, this references the current LineItem.
Thanks to the responses to this question I was able to write a higher order component that accepts a callback function as an argument. Here is the code as an example:
Array.prototype.myFunction = function (callback) {
const items = this
const newArray = []
for (let item of items) {
item = callback(item)
newArray.push(item)
}
return newArray
}
const array = [1, 2, 3, 4]
const result = array.myFunction((item => {
return item + 1
}))
console.log(result)
I am wondering why I need the PhoneNumberFormatter.prototype.slice method below.
Why can't I just use slice(3,6).join('') inside my other methods without needing to add PhoneNumberFormatter.prototype.slice method? When the interpreter doesn't find the method on the PhoneNumberFormatter object, wouldn't it just look up the prototype chain to find slice and join on the Array prototype?
function PhoneNumberFormatter(numbers) {
this.numbers = numbers;
}
PhoneNumberFormatter.prototype.render = function() {
var string = '';
string += this.parenthesize(this.getAreaCode());
string += ' ';
string += this.getExchangeCode();
string += '-';
string += this.getLineNumber();
return string;
};
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.slice(0, 3);
};
PhoneNumberFormatter.prototype.getExchangeCode = function() {
return this.slice(3, 6);
};
PhoneNumberFormatter.prototype.getLineNumber = function() {
return this.slice(6)
};
PhoneNumberFormatter.prototype.parenthesize = function(string) {
return '(' + string + ')';
};
// why do I need the following method?
PhoneNumberFormatter.prototype.slice = function(start, end) {
return this.numbers.slice(start, end).join('');
};
var phoneNumberOne = new PhoneNumberFormatter([6, 5, 0, 8, 3, 5, 9, 1, 7, 2]);
phoneNumberOne.render()
I guess it was created to make the code cleaner and prevents code duplication.
As the use of the slice keyword in two different places seems to confuse you I'll explain briefly the differences.
In your prototype methods (e.g. getAreaCode, getExchangeCode, ...), the keyword this represents a PhoneNumberFormatter object. When you call this.slice() (in the methods), you are calling the slice method of this object hence the one created in your code.
But in your slice method (the one in your code), you are calling this.numbers.slice(). Here you call the slice method on an array (this.numbers). You are using the native array method slice.
You could write your methods like so and remove the slice method created in your code:
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.numbers.slice(0, 3).join('');
};
I think the main confusion you seem to have is the name of the method slice. This leads you to believe that it is the array method, but in fact it is not.
The slice method mentioned in your code is the slice method of the PhoneNumberFormatter, not the one of the array.
Because of this, the interpreter could never find the slice method in the prototype chain, because the prototype of the PhoneNumberFormatter would be object, and just calling slice would rather throw an error that the method is undefined.
The this.slice method refers to PhoneNumberFormatter.prototype.slice and this one will refer to it's own numbers property and will then call the slice method on the numbers Array.
Maybe it is simply easier to rename the code like:
function PhoneNumberFormatter( numberArr ) {
this.numbers = numberArr.slice(); // copy numbers
}
PhoneNumberFormatter.prototype.getAreaCode = function() {
return this.take(0, 3);
};
PhoneNumberFormatter.prototype.take = function() {
return Array.prototype.splice.apply( this.numbers, arguments ).join('');
};
var formatter = new PhoneNumberFormatter([0,1,2,3,4,5,6,7,8,9]);
console.log(formatter.getAreaCode());
Which maybe makes it more clear to you, that the take method is simply a utility method simplifying your code, cause be honest, why would you want to repeat for 5 different methods the slice and join part, and then take a potential risk of copying an error 5 times, or in case you need to change something, need to make the same change 5 times
I'm looking for a javascript function that can:
Condition (I)
compose another function when it does not have recursion in its definition, kind of like in maths when the function is given a power, but with multiple arguments possible in the first input - e.g. with a (math) function f:
f(x) := x+2
f5(x) = f(f(f(f(f(x))))) = x+10
Condition (II)
Or maybe even input custom arguments into each step of composition:
(52)2)2=
Math.pow(Math.pow(Math.pow(5,2),2),2) = Math.pow.pow([5,2],2,["r",2]])
//first arg set, how times the next, 2nd arg set - "r" stands for recursion -
//that argument will be occupied by the same function
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,2]]) //-> 390625
2((52)3)=
Math.pow(2,Math.pow(Math.pow(5,2),3)) = Math.pow.pow([5,2],["r",2],["r",3],[2,"r"])
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,3]]) //-> 244140625
_.supercompose(Math.pow,[[5,2],[_,2],[_,3],[2,_]]) //-> Infinity (bigger than the max. number)
Note: The above are just templates, the resulting function doesn't have to have the exact arguments, but the more close to this (or creative, for example, a possibility of branching off like this ->[2,4,"r",4,2,"r"], which would also be complicated) the better.
I've been attempting to do at least (I) with Function.prototype, I came up with this:
Object.defineProperty(Function.prototype,"pow",{writable:true});
//Just so the function not enumerable using a for-in loop (my habit)
function forceSlice(context,argsArr)
{returnArray.prototype.slice.apply(context,argsArr)}
Function.prototype.pow = function(power)
{
var args=power<2?forceSlice(arguments,[1]):
[this.pow.apply(this,[power-1].concat(forceSlice(arguments,[1])))];
return this.apply(0,args);
}
//Usage:
function square(a){return a*a;}
square.pow(4,2) //65536
function addThree(a,b){return a+(b||3); }
// gives a+b when b exists and isn't 0, else gives a+3
addThree.pow(3,5,4) //15 (((5+4)+3)+3)
Worst case, I might just go with eval, which I haven't figured out yet too. :/
Edit: Underscore.js, when played around with a bit, can fulfill both conditions.
I came up with this, which is close to done, but I can't get it to work:
_.partialApply = function(func,argList){_.partial.apply(_,[func].concat(argList))}
_.supercompose = function(func,instructions)
{
_.reduce(_.rest(instructions),function(memo,value)
{
return _.partialApply(_.partialApply(func, value),memo)();
},_.first(instructions))
}
//Usage:
_.supercompose(Math.pow,[[3,2],[_,2]]) //should be 81, instead throws "undefined is not a function"
Edit: jluckin's cleareance of terms (recursion-> function composition)
Edit: made example function return number instead of array
The term you are looking for is called function composition, not necessarily recursion. You can apply function composition in javascript easily since you can pass a function as an argument.
I created a small function called compose, which takes a function, an initial value, and the number of times to compose the function.
function compose(myFunction, initialValue, numberOfCompositions) {
if (numberOfCompositions === 1) {
return myFunction(initialValue);
}
else {
return compose(myFunction, myFunction(initialValue), --numberOfCompositions);
}
}
When this function is evaluated, you pass in some function f(x), some initial x0, and the repeat count. For example, numberOfCompositions = 3 gives f(f(f(x)));
If there is one composition, then f(x) is returned. If there are two compositions, compose returns f(x) with f(x) replacing x as the argument, with 1 passed in as the composition so it will evaluate f(f(x)).
This pattern holds for any number of compositions.
Since functions are treated as objects and can be passed as arguments of functions, this method basically wraps your "non-recursive" functions as recursive functions to allow composition.
Success(simplicity wins):
_.supercompose = function (func,instructions,context)
{
var val;
for(var i = 0; i < instructions.length; i++)
{
val = _.partial.apply(_,[func].concat(instructions[i])).apply(context||this,val?[val]:[]);
}
return val;
}
//Usage (with a function constructor for operations):
_.op = function(o){return Function.apply(this,"abcdefghijklmnopqrstuvwxyz".split("").concat(["return " + o]))}
_.op("a+b")(3,5) //-> 8
_.op("a*b")(3,5) //-> 15
_.supercompose(_.op("(a+b)*c*(d||1)"),[[1,2,3],[-5,_,1],[1,2,_,3]])
//-> (1+2)*((-5+((1+2)*3))*1)*3 -> 36
I'd like to call a function using an array as parameters:
const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it
function call_me (param0, param1, param2 ) {
// ...
}
Is there a better way of passing the contents of x into call_me()?
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply().
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);
Why don't you pass the entire array and process it as needed inside the function?
var x = [ 'p0', 'p1', 'p2' ];
call_me(x);
function call_me(params) {
for (i=0; i<params.length; i++) {
alert(params[i])
}
}
In ES6 standard there is a new spread operator ... which does exactly that.
call_me(...x)
It is supported by all major browsers except for IE.
The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.
Assuming that call_me is a global function, so you don't expect this to be set.
var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
As #KaptajnKold had answered
var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);
And you don't need to define every parameters for call_me function either.
You can just use arguments
function call_me () {
// arguments is a array consisting of params.
// arguments[0] == 'p0',
// arguments[1] == 'p1',
// arguments[2] == 'p2'
}
While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.
function callMe(...arr){ //valid arguments
alert(arr);
}
function callMe(name, ...arr){ //valid arguments
alert(arr);
}
function callMe(...arr, name){ //invalid arguments
alert(arr);
}
If you need to pass an array as the starting argument you can do:
function callMe(arr, name){
let newArr = [...arr];
alert(newArr);
}
Function arguments may also be Arrays:
function foo([a,b,c], d){
console.log(a,b,c,d);
}
foo([1,2,3], 4)
of-course one can also use spread:
function foo(a, b, c, d){
console.log(a, b, c, d);
}
foo(...[1, 2, 3], 4)
Note this
function FollowMouse() {
for(var i=0; i< arguments.length; i++) {
arguments[i].style.top = event.clientY+"px";
arguments[i].style.left = event.clientX+"px";
}
};
//---------------------------
html page
<body onmousemove="FollowMouse(d1,d2,d3)">
<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>
</body>
can call function with any Args
<body onmousemove="FollowMouse(d1,d2)">
or
<body onmousemove="FollowMouse(d1)">
you can use the spread syntax
for example:
function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document
you can use spread operator in a more basic form
[].concat(...array)
in the case of functions that return arrays but are expected to pass as arguments
Example:
function expectArguments(...args){
return [].concat(...args);
}
JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.
So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:
function hash() {
return arguments[0]+','+arguments[1];
}
hash(1,2); // "1,2" whoaa
So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!
The natural solution would be to use arr.join method:
function hash() {
return arguments.join();
}
hash(1,2,4,..); // Error: arguments.join is not a function
Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?
function hash() {
return [].join.call(arguments);
}
hash(1,2,3,4); // "1,2,3,4" whoaa
The trick is called method borrowing.
We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.
Why does it work?
That’s because the internal algorithm of the native method arr.join(glue) is very simple.
Taken from the specification almost “as-is”:
Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.
So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.
There's a better way using JSON not an Array!
// Call a function with a Json Key / Value Pair:
sendMail({param1: p1, param2: p2});
// Function definition and usage of value pairs:
function sendMail(data){
var parameter1 = data.param1;
var parameter2 = data.param2;
}
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!