What does "a.call.apply(a.bind, arguments)" mean? - javascript

Just because of curiosity I wanted to make a bounded function with this particular approach :
var fn = function(a, b, c) {
return a.call.apply(a.bind, arguments)
}
var boundFn = function(a, b, c) {
fn.apply(null, arguments)
}
function unboundedFn() {
console.log(this, arguments)
}
var boundedFn = boundFn(unboundedFn, x, y);
So I'm trying to understand what a.call.apply(a.bind, arguments) do exactly ?

If You have a function like this:
function unboundedFn() {
console.log(this, arguments)
}
You can use unboundedFn.call(thisObj, arg1, arg2) or unboundedFn.apply(thisObj, [arg1, arg2]) to run it, but changing what this means inside. Both call and apply do the same, and only difference is way of passing arguments.
Becouse call, apply and also bind are methods, you can run for example unboundedFn.call.call.call.call.apply.apply.apply.apply(), but it doesn't seem to have to much sense.
In your example return a.call.apply(a.bind, arguments) is equal to return a.bind.call(...arguments), which is equal to a.bind(...arguments.slice(1)), so whole fn function can be simplified to:
function fn(a,b,...args){
return a.bind(b, ...args);
}

Related

Returning a function with the arguments reversed

The code that I am practicing with is where I have a function called InReverse. This function accepts a function as an argument and returns a function. When the function returned is invoked, it reverses the order of the arguments.
When the returned functions are returned:
const catDog = ('cat', 'dog') => returns ('dog cat')
What I have rewritten out so far is:
function inReverse (func) {
return function (...arguments) {
return arguments.map((element) => {
element.reverse();
});
}
}
Any guidance would be appreciated!
You need to simply call the input function inside the newly created anonymous function.
For example this works:
function inReverse(f) {
return function () {
let args = [...arguments].reverse();
return f.apply(this, args);
}
}
So for example if you have subtract function like this:
function subtract(a, b) {
return a-b;
}
subtract(1, 10); will be -9 as expected.
and inReverse(subtract)(1, 10) will be 9 as expected.
Not sure why you're using map, just call reverse right on the arguments array. Also you weren't calling func:
function inReverse(func) {
return function(...args) {
return func(...args.reverse());
};
}
(Notice that arguments is a reserved identifier in strict mode, you should name your parameter for something else)
Not sure, why you are using map method, just use reverse method in your function right on the arguments. Reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse?retiredLocale=id
Just reverse the arguments, and use func.apply(this, arr)
function inReverse(func) {
return function() {
var args = Array.prototype.slice.call(arguments)
args = args.reverse();
return func.apply(this, args);
}
}
function div(a, b) {
return a / b
}
console.log(div(1, 2))
console.log(inReverse(div)(1, 2))

Purpose of call with null in curry function (JavaScript implementation)

In the following implementation of curry function here:
// curry :: ((a, b, ...) -> c) -> a -> b -> ... -> c
function curry(fn) {
const arity = fn.length;
return function $curry(...args) {
if (args.length < arity) {
return $curry.bind(null, ...args);
}
return fn.call(null, ...args);
};
}
what's the purpose of using call with null as this in the fn.call? Wouldn't just fn(...args) work? I did try some examples and got the same results.
Yes, it would work just fine. (The tiny difference is that it passes undefined instead of null for the this context).
So why did the author use .call(null, …)? Probably because it nicely mirrors the .bind(null, …) call.

Wrapper function in Javascript

I understand wrapper would be something like
var str = 'Hello World'; // assigning string to a variable
console.log(str); // 'Hello World'
var str2 = new String('Hello World') // Creating a wrapper function
str2.valueOf() // 'Hello World'
By that logic, can the below example also be considered a wrapper function
function SuperOuterAdd(a, b){
console.log('Wrapper 2');
return OuterAdd(a, b);
}
function OuterAdd(a, b){
console.log('Wrapper 1');
return add(a, b);
}
function add(a, b){
return parseInt(a) + parseInt(b);
}
There's no language definition of wrapper function in JavaScript, and from your code, new String('Hello World'), is an instantiation of a string object - I don't see how that would be considered a wrapper function by any logic at all.
A wrapper function is a design concept where a very minimal function is using another function to do it's "work" for it, sometimes using a slightly different set of arguments.
for example:
function power(x, y) {
var res = 1;
while(y--) {
res *= x;
}
return res;
}
function square(x) {
return power(x, 2);
}
In the code above square is a wrapper function.
Wrappers are a loose term for a function that simply returns a value, with no computation. They are useful when we need a value, but not right away. Maybe the result is not ready yet when you define it, or you need some binding for the function to work (use of this).
Neither of the examples you provided is a wrapper function. The first one is simply an object instantiation (you're not even creating a function). It just so happens that the String constructor can take a string literal as an argument, which means it can work like the identity function. In the second, it's just some more elaborate contraption, but it's still function calling and computing things.
In general, wrapper functions are pretty useless out of context, and they're mostly a Javascript-specific thing, but consider the following:
let foo = null;
fetch('/my/api/call').then(function(res) {
foo = res;
getFoo(); // => [your object]
});
getFoo(); // => null
function getFoo() {
return foo;
}
Here is the example:
function SimpleWrapper() {
var self = this;
initialize();
function initialize() {
self.SuperOuterAdd = SuperOuterAdd;
self.OuterAdd = OuterAdd;
}
function SuperOuterAdd(a, b){
console.log('Wrapper 2');
return OuterAdd(a, b);
}
function OuterAdd(a, b){
console.log('Wrapper 1');
return _add(a, b);
}
function _add(a, b){
return parseInt(a) + parseInt(b);
}
}

Function closures

Hi I'm trying to run the following function:
function add (a, b) {
return a + b;
}
var make_lazy = function (add, a, b) {
return function () {
add(a,b);
}
}
Basically what I'm trying to do is to pass another function as an argument and its parameters to the make_lazy function - and then run the function that was passed in as the argument along with the other two parameters. I get undefined is not function as an error when I try to run the code.
You forgot the return statement in the anonymous function that you're returning from make_lazy:
var make_lazy = function (add, a, b) {
return function () {
return add(a,b) // <----- here
}
}
I think you are trying for something like this.
function add (a, b) {
return a + b;
}
var make_lazy = function (a, b) {
return function () {
return add(a,b);
}
}
Then you can call var lazy = make_lazy(3,5); and later call lazy() to get 8
Wrap you lazy function body inside a self calling function and return.
function add (a, b) {
return a + b;
}
var make_lazy = function (add, a, b) {
return (function () {
add(a,b);
})();
}
Here's my point of view.
When you assign a function to make_lazy variable, after that you should make an invocation make_lazy() with the same params as they were in the definition of that function:
make_lazy(function expression, a, b);
This portion:
function (add, a, b)
just makes add a local variable, this is not the same as add(a,b) which is defined above.
To make the code work, try to invoke make_lazy as
make_lazy(add, 3, 4)

I'm reading Eloquent Javascript and I am a little confused by this partial function example. Please help explain

function asArray(quasiArray, start) {
var result = [];
for (var i = (start || 0); i < quasiArray.length; i++)
result.push(quasiArray[i]);
return result;
}
function partial(func) {
var fixedArgs = asArray(arguments, 1);
return function(){
return func.apply(null, fixedArgs.concat(asArray(arguments)));
};
}
function compose(func1, func2) {
return function() {
return func1(func2.apply(null, arguments));
};
}
var isUndefined = partial(op["==="], undefined);
var isDefined = compose(op["!"], isUndefined);
show(isDefined(Math.PI));
show(isDefined(Math.PIE));
Why can't the function compose simply return:
func1(func2);
and give the proper output. I thought the partial function which is stored in the variable isUndefined already returns func.apply(null, [fixed, arguments])
var op = {
"+": function(a, b){return a + b;},
"==": function(a, b){return a == b;},
"===": function(a, b){return a === b;},
"!": function(a){return !a;}
/* and so on */
};
Both partial and compose are higher-order functions.
isUndefined will return a function that, when invoked, will invoke the originally passed function with the original arguments plus any new arguments passed at invocation.
To answer your question, you'd be calling apply on the function returned from partial which will in turn, call apply on the function originally passed to partial.
You want compose to return a function that when called, will return the result of calling the first function passed the second function as an argument (with the second function passed the arguments passed to the compose invocation). If compose returned func1(func2), then you'd assign the result of the invocation to the variable isDefined.
EDIT:
Now that we have op, let's try to decompose this:
var isUndefined = partial(op["==="], undefined);
this is equivalent to
var isUndefined = partial(function(a, b){return a === b;}, undefined);
isUndefined is assigned a function that, when called, will call the function passed as the first argument to partial, passing in undefined as the first argument to that function call, followed by the arguments passed to the function isUndefined i.e.
partial(function(a, b){return a === b;}, undefined /* this will become 'a' when isUndefined is invoked */)(argumentForisUndefined /* this will become 'b' when isUndefined is invoked */);
isDefined composes isUndefined with another function that negates the result of isUndefined.
var isDefined = compose(op["!"], isUndefined);
is equivalent to
var isDefined = compose(function(a){return !a;}, isUndefined);
which is equivalent to (renamed variables for clarity)
var isDefined = compose(
function(a){return !a;},
partial( /* partial function becomes 'a' passed to first function */
function(b, c) {
return b === c;
},
undefined /* undefined becomes 'b' passed to partial */
)
)(argumentForisDefined /* argumentForisDefined becomes 'c' passed to partial */);
If we look at what we have so far and substituting for readability, boils down to a function that takes an argument and compares it to undefined, negates the result and returns a boolean
var isDefined = function (b) { return !undefined === b; }
So lets simply dissect it. Assuming we have this compose function:
function compose(func1, func2) {
return func1(func2.apply(null, arguments));
}
What will happen when you use it like this?
a = compose(function(){console.log(1)}, function(){console.log(2)});
The second function would be call immediately outputting 2, and straight afterwards the first function will be called outputting 1. a will be undefined, because the first function does not return anything.
What you want combine to do, is to return a new function, that combines the two other functions and that you can call at will.
Doing the above all on the original compose, will return a new function, that, when you call it with a() will output 2 and then 1.

Categories