Я знаю, что опаздываю на вечеринку, но вот более короткий метод, который больше соответствует вашим первоначальным попыткам.
a.replace('f', String.call.bind(a.toUpperCase));
Итак, где вы ошиблись и что это за новое вуду??
Задача 1
Как указано выше, вы пытались передать результаты вызванного метода в качестве второго параметра String.prototype.replace () , когдавместо этого вы должны передавать ссылку на функцию
Решение 1
Это достаточно просто решить.Простое удаление параметров и круглых скобок даст нам ссылку, а не выполнение функции.
a.replace('f', String.prototype.toUpperCase.apply)
Задача 2
Если вы попытаетесь запустить код сейчас, вы получите сообщение о том, что неопределенноене является функцией и поэтому не может быть вызвана.Это потому, что String.prototype.toUpperCase.apply на самом деле является ссылкой на Function.prototype.apply () через прототипическое наследование JavaScript.То, что мы на самом деле делаем, выглядит примерно так:
a.replace('f', Function.prototype.apply)
Что явно не то, что мы намеревались.Как узнать, что Function.prototype.apply () в String.prototype.toUpperCase () ?
Решение 2
Использование Function.prototype.bind () мы можем создать копию Function.prototype.call с его контекстом, специально установленным в String.prototype.toUpperCase.Теперь у нас есть следующая
a.replace('f', Function.prototype.apply.bind(String.prototype.toUpperCase))
Проблема 3
Последняя проблема заключается в том, что String.prototype.replace () будет передавать несколько аргументов своей функции замены.Однако Function.prototype.apply () ожидает, что вторым параметром будет массив, но вместо этого он получит либо строку, либо число (в зависимости от того, используете ли вы группы захвата или нет).Это приведет к ошибке списка недопустимых аргументов.
Решение 3
К счастью, мы можем просто заменить в Function.prototype.call () (которая принимает любое количество аргументов, ни один из которых не имеет ограничений типа) для Function.prototype.apply () .Теперь мы пришли к рабочему коду!
a.replace(/f/, Function.prototype.call.bind(String.prototype.toUpperCase))
Сброс байтов!
Никто не хочет набирать prototype несколько раз.Вместо этого мы будем использовать тот факт, что у нас есть объекты, которые ссылаются на одни и те же методы через наследование.Конструктор String, будучи функцией, наследует от прототипа Function.Это означает, что мы можем заменить в String.call Function.prototype.call (на самом деле мы можем использовать Date.call для сохранения еще большего количества байтов, но это менее семантически).
Мы также можемиспользуйте нашу переменную 'a', поскольку ее прототип содержит ссылку на String.prototype.toUpperCase , которую мы можем поменять с помощью a.toUpperCase.Это комбинация из трех решений, приведенных выше, и этих мер по экономии байтов - вот как мы получаем код в верхней части этого поста.