Главный косяк:
tableValues(element);
Как вы собираетесь перебирать элемент? Это абсурд. Должно быть
element.children
/
element.childNodes
.
Косяки помельче:
document.querySelector('form').childNodes
Поскольку вам нужны только input'ы и select'ы, то не надо перебирать заведомо лишнее - используйте
children
вместо
childNodes
. Ну и погуглите, в чём между ними разница.
if (element.nodeType == 1 && element.nodeName == 'INPUT' || element.nodeName == 'SELECT') {
Проверка значения
nodeType
лишняя. Кроме того, вам не помешает разобраться с приоритетом выполнения операторов -
nodeType
вы тут проверяете только для input'а.
let result = [];
Почему эта штука объявляется вне функции, а наполняется внутри? Что, перед каждым вызовом функции будете вручную обнулять результат? Надо создавать массив со значениями внутри функции, и возвращать его как результат её выполнения.
Ну и конечно всё это делается несколько короче:
const getValues = el =>
el instanceof Element
? [ 'INPUT', 'SELECT' ].includes(el.tagName)
? [ el.value ]
: [...el.children].flatMap(getValues)
: [];
// или
const getValues = el =>
[ 'INPUT', 'SELECT' ].includes(el?.tagName)
? [ el.value ]
: [].flatMap.call(el.children ?? [], getValues);
const values = getValues(document.querySelector('form'));
Или ещё короче - если без рекурсии:
const values = Array.from(document.querySelector('form').elements, n => n.value);
А вообще, можно и в более общем виде задачу решить - если сделать проверку узла и получение данных из него параметрами функции:
const getFromDOMNodes = (node, test, getVal) =>
node instanceof Node
? Array.prototype.reduce.call(
node.childNodes,
(acc, n) => (acc.push(...getFromDOMNodes(n, test, getVal)), acc),
test(node) ? [ getVal(node) ] : []
)
: [];
const values = getFromDOMNodes(
document.querySelector('form'),
node => [ 'INPUT', 'SELECT' ].includes(node.nodeName),
node => node.value
);