Какие есть косяки:
- Перебираете вложенные узлы, но замену выполняете у того, что передан в функцию.
- Заменять содержимое надо только у текстовых узлов - чтобы проверить тип, смотрим nodeType.
- У текстовых узлов нет innerText. Есть textContent и nodeValue.
- Зачем функции знать заранее, что за замена должна быть выполнена? Что будете делать, если понадобится выполнить другую замену - закопипастите функцию, заменив регулярку? Лучше добавим второй параметр - функцию, принимающую текущий текст и возвращающую новый.
Исправляем:
function replaceText(node, replacer) {
if (node.nodeType === Node.ELEMENT_NODE) {
node.childNodes.forEach(n => replaceText(n, replacer));
} else if (node.nodeType === Node.TEXT_NODE) {
node.textContent = replacer(node.textContent);
}
}
replaceText(document.body, str => str.replace(/\d/g, 'hello, world!!'));
Или, долой рекурсию и проверки типов узлов, можно сразу текстовые перебирать:
function replaceText(node, replacer) {
const iter = document.createNodeIterator(node, NodeFilter.SHOW_TEXT);
for (let n = null; n = iter.nextNode();) {
n.nodeValue = replacer(n.nodeValue);
}
}