Traveling Tech Guy
Traveling Tech Guy

Reputation: 27809

Binding a Javascript function to a variable

I'm trying to bind one of either toLowerCase or toUpperCase to a variable, and I'm missing some step along the way. Here's a simplified version of my code:

for(let i = 0; i < arr.length; i++) {
    if(flag) {
        arr[i] = arr[i].toUpperCase();
    }
    else {
        arr[i] = arr[i].toLowerCase();
    }
}

I'm hoping I can do something like:

let func = flag  ? String.prototype.toUpperCase : String.prototype.toLowerCase;
arr = arr.map(x=>func(x));

While I can set the function, it looks like I'm not using it right, as I'm getting Uncaught TypeError: String.prototype.toLowerCase called on null or undefined. What am I missing here?

Upvotes: 2

Views: 51

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074425

You can do it that way, but you have to use .call (or .apply) so you set this correctly within the call to toUpperCase/toLowerCase, since they expect to see the string to use as this, not as a passed parameter:

let func = flag  ? String.prototype.toUpperCase : String.prototype.toLowerCase;
arr = arr.map(x=>func.call(x));
//-------------------^^^^^

(I also dropped the let from in front of arr on the second line, as otherwise arr on the right-hand side of the = would be undefined. [Or, depending on where/how arr was previously declared, it would be an error.])

Example:

let arr = ["one", "TWO", "three", "FOUR"];
const flag = Math.random() < 0.5;
console.log("Flag is: " + flag);
let func = flag  ? String.prototype.toUpperCase : String.prototype.toLowerCase;
arr = arr.map(x=>func.call(x));
console.log(arr);

Another option is to give yourself a wrapper function, which you can then call the way you wanted to call it:

let func = flag ? s => s.toUpperCase() : s => s.toLowerCase();
arr = arr.map(x=>func(x));

Example:

let arr = ["one", "TWO", "three", "FOUR"];
const flag = Math.random() < 0.5;
console.log("Flag is: " + flag);
let func = flag ? s => s.toUpperCase() : s => s.toLowerCase();
arr = arr.map(x=>func(x));
console.log(arr);

But the easier thing in this specific case is to just use brackets notation and a string function name:

let funcName = flag  ? "toUpperCase" : "toLowerCase";
arr = arr.map(x=>x[funcName]());

Example:

let arr = ["one", "TWO", "three", "FOUR"];
const flag = Math.random() < 0.5;
console.log("Flag is: " + flag);
let funcName = flag  ? "toUpperCase" : "toLowerCase";
arr = arr.map(x=>x[funcName]());
console.log(arr);

Upvotes: 5

kukkuz
kukkuz

Reputation: 42352

You can call the function using func.call(x) - see demo below:

let func = true  ? String.prototype.toUpperCase : String.prototype.toLowerCase;
let arr = ['test', 'TEST', "Test"].map(x=>func.call(x));
console.log(arr);

Upvotes: 2

Related Questions