Переход с такого языка, как Ruby, на Javascript может вызвать у программиста желание получить недостающие функции, синтаксис и просто легко читаемый код. Такие простые вещи, как переворачивание строки, требуют создания новой функции, а не простого произнесения «gnirts».reverse. Итак, как мы можем добавить немного дополнительной функциональности в наш проект, не повторяясь?

Введите исправление обезьяны! Попросту говоря, Monkey patching — это изменение поведения существующего кода без изменения самого кода. Это может означать что угодно, от расширения поведения типа данных до полного подавления существующих функций.

Давайте уберем слона с дороги: Monkey Patching — плохая практика. Несмотря на то, что несколько небольших изменений здесь и там в экспериментальных целях не нарушат ваш код, их использование в реальных продуктах может привести к непреднамеренному поведению, особенно при переопределении поведения существующих методов или при использовании разных источников( т.е. библиотеки или модули) пытаются изменить одну и ту же функциональность.

С этим покончено, давайте перейдем к тому, как мы на самом деле делаем Monkey Patch в JS. Первый и самый безопасный подход — создать объект, который будет содержать в себе все наши пропатченные функции. Для этого примера давайте добавим обратную функциональность:

var Utility = {
  reverse: function rec(string){
    return string === '' ? '' 
           : rec(string.substring(1)) + string.charAt(0);
  }
}

Как только наш объект определен, мы можем просто вызвать его, сославшись на объект и вызвав свойство reverse, в котором находится наша рекурсивная функция reverse. Вот так:

var reverseMe = "gnirts"
console.log(Utility.reverse(reverseMe)); => 'string'

Как мы видим, мы мало что делаем для самого существующего кода, просто добавляем функциональные возможности в легко доступной форме. При этом мы можем затем экспортировать этот объект в другие файлы и использовать наши служебные функции. Тем не менее, мы также можем напрямую влиять на String.prototype в нашем втором, хотя и более опасном, методе исправления обезьян, о котором я расскажу. Для этого просто вызовите прототип, который вы хотите изменить, и назначьте ему функцию:

String.prototype.stringMap = function(){ 
  return 'I am stringMap';
}
'ayy'.stringMap(); => 'I am stringMap'

Здорово! Теперь у нас есть рабочее расширение для нашего прототипа, давайте создадим метод, который позволит нам использовать функциональность Array.map для строки, разделив строку на массив-> сопоставив наши изменения с некоторыми параметрами-> и воссоединив массив в строку.

String.prototype.stringMap = function(change ,replace=false,splitBy = ''){
  if(replace){
    return this.split(splitBy).map(el=>change).join(splitBy);
  }
  return this.split(splitBy).map(el=>el += change).join(splitBy);
};

console.log('Add a period after every space'.stringMap('.', false,' ')); // => "Add. a. period. after. every. space."
console.log('replace word with \'franisawesome\'.'.stringMap('franisawesome',true,' ')); 
//=> franisawesome franisawesome franisawesome franisawesome

Как вы, вероятно, заметили, этот метод stringMap не очень надежен и не включает в себя полную функциональность того, что может сделать карта массива; тем не менее, теперь мы исправили String.prototype и добавили в язык свои собственные пользовательские функции, насколько это круто?

Я не утверждаю, что являюсь экспертом в области обезьяньих исправлений и не ратую за их использование в проектах, но я думаю, что это интересная концепция, с которой можно повозиться.

Надеюсь, вам понравилась запись!