Jorjon
Jorjon

Reputation: 5434

Reference a function using call

I'm trying to reference a Javascript built-in function, but I can't manage to make a reference to call function and use it under another name.

Requirements are:

const s = 'ABCDEFG';
console.log(''.toLowerCase.call(s)); // Correctly outputs 'abcdefg'
const foo = ''.toLowerCase.call;
console.log(foo); // Correctly outputs 'function call() { [native code] }'
foo(s); // Throws 'foo is not a function'

To compare, if I use my own function, the function reference works.

function call (x) {
  return x.toLowerCase();
}

const s = 'ABCDEFG';
console.log(call(s)); // Outputs 'abcdefg'
foo = call;
console.log(foo); // Outputs 'function...'
foo(s); // 'abcdefg'

Maybe functional features of Javascript such as partials or currying would help, but I can't understand how to make it work.

Upvotes: 1

Views: 66

Answers (2)

Nikola Dimitroff
Nikola Dimitroff

Reputation: 6237

Use this:

foo = String.prototype.toLowerCase.call.bind(String.prototype.toLowerCase)
foo(s)

or this:

foo = String.prototype.toLowerCase.call;
foo.call(String.prototype.toLowerCase, s)

It seems very counter intuitive but in fact all call functions on all native functions are exactly the same. The JS engine doesn't create separate functions (as it usually does for non-native invocations). This means that in order to invoke the call, you need provide its this as first argument as I am doing in the examples above - either by calling foo.call(ActualFunction) or by binding. Here's a short snippet that shows that all call functions are actually the same:

let x = String.prototype.toLowerCase.call;
let y = String.prototype.toUpperCase.call;
let z = String.prototype.indexOf.call;
console.log(Object.is(x, y));
console.log(Object.is(x, z));
// Even across different prototypes!
let w = parseInt.call;
console.log(Object.is(x, w));

Upvotes: 1

Pulkit Aggarwal
Pulkit Aggarwal

Reputation: 2672

You can use foo as a function:

const foo = function(data){ 
    return ''.toLowerCase.call(data)
};  

Now call foo(s), it gives the expected result:

const foo = function(data) {
  return ''.toLowerCase.call(data)
};

const s = 'ABCDEFG';
console.log(foo(s))

Upvotes: 1

Related Questions