Переход с такого языка, как 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 и добавили в язык свои собственные пользовательские функции, насколько это круто?
Я не утверждаю, что являюсь экспертом в области обезьяньих исправлений и не ратую за их использование в проектах, но я думаю, что это интересная концепция, с которой можно повозиться.
Надеюсь, вам понравилась запись!