Предотвращение ограбления банка путем переопределения нативных прототипов в JavaScript

Если вы не читали мою предыдущую статью и не знакомы с тем, что означает переопределение нативных прототипов, ознакомьтесь с ней здесь

При первом взгляде на название этой статьи вы можете подумать, предотвратить ограбление банка с помощью JavaScript? Как это работает?

Я хотел бы сравнить DOM вашего сайта с вашим банковским счетом. Это ваша частная собственность, и вы должны решать, как и когда ее использовать. В этой статье я хотел бы изучить доступные варианты, доступные разработчикам, чтобы дать им возможность управлять DOM.

Сначала бросается в глаза вариант использования MutationObserver. Беглый просмотр любимого всеми разработчиками ресурса говорит о Mutation Observers следующее.

Интерфейс MutationObserver позволяет отслеживать изменения, вносимые в дерево DOM.

Используя MutationObserver, мы можем получать уведомления о добавлении элементов в DOM. Нам также предоставляется, какие элементы были добавлены в DOM. То, что мы могли бы сделать, это:

  1. Обработчик MutationObserver запускается с добавленными узлами
  2. Затем мы можем просмотреть добавленные узлы и сказать для каждого узла
  3. Если добавленный узел не является «грабителем», ничего не делать
  4. Если добавленный узел является «разбойником», удалите его из DOM.

Проблема с этим решением становится очевидной на 4-м шаге. К тому времени, когда наблюдатель мутаций уведомляется об изменении DOM, уже слишком поздно. «Разбойник» уже добавлен в DOM.

Это подводит нас к решению, ради которого вы пришли сюда.
Переопределение. Родной. Прототипы. 🥳

Вкратце: переопределение нативных прототипов включает в себя переопределение метода или свойства, существующего в прототипе нативного объекта. Например:

Array.prototype.push = ()=> {console.log('overridden')}
Array.prototype.filter = ()=> {console.log('overridden')}
Function.prototype.call = ()=> {console.log('overridden')}

После запуска любого из приведенных выше кодов все последующие вызовы любого из этих методов будут печатать определенный оператор журнала.

Итак, как это связано с перехватом добавляемых узлов в DOM, спросите вы? Что ж, один из способов добавления элементов в DOM — использование метода appendChild. Но откуда этот метод? Быстрый поиск в Google показывает, что он существует в прототипе Node Node.prototype.appendChild. Зная это, создать решение должно быть довольно легко.

Давайте рассмотрим, как работает это решение.

  1. Line 2 Сохраните ссылку на собственный метод appendChild
  2. Line 5 Переопределить собственный метод appendChild
  3. Line 7 Если добавленный узел имеет идентификатор «грабитель», не добавляйте его
  4. Line 14 На самом деле добавить узел в DOM
  5. Line 18-28 Выполните настройку, чтобы продемонстрировать работу этого решения.

Очевидным преимуществом этого подхода является то, что «грабитель» никогда не добавляется к DOM. Недостаток этого подхода по сравнению с MutationObserver заключается в том, что существует гораздо больше способов добавления элементов в DOM, и все они должны быть переопределены.

Я надеюсь, что эта статья была информативной. Оставайтесь с нами для следующего.