2

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?

5
  • 2
    They're methods. You need to call them on x, not pass it as an argument. Commented Aug 30, 2017 at 17:10
  • 1
    Have a look at this question for what you are trying to do. Commented Aug 30, 2017 at 17:11
  • 1
    Use .callfor such things (or .apply, whatever). Commented Aug 30, 2017 at 17:11
  • FYI, as you were ticking the "accept" checkmark, I added to the middle of my answer. :-) Commented Aug 30, 2017 at 17:24
  • 1
    Thanks for letting me know @T.J.Crowder. I went with your first suggestion. Code already working :) Commented Aug 30, 2017 at 17:26

2 Answers 2

5

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);

Sign up to request clarification or add additional context in comments.

Comments

2

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.