Написание многоразовой функции while декларативным способом - PullRequest
0 голосов
/ 16 апреля 2020

Я делаю небольшой проект и инициализирую объект множеством свойств и методов, некоторые из которых будут ссылаться на объект самостоятельно, чтобы получить какое-то другое свойство (в настоящее время у меня есть только один такой). Поскольку я не могу получить доступ к другим свойствам объекта во время инициализации, я решил заменить самоссылающиеся свойства в функциях, называемых init, которые возвращают undefined, если одно из необходимых свойств не определено. Это то, что у меня есть в настоящее время (я собираюсь проверить, существует ли gameTemplates, а затем заменить его на функцию):

generateCorrectGuess: function init() {
                    if (gameTemplates.numberOfElements === undefined || (gameTemplates.numberOfElements instanceof Function && gameTemplates.numberOfElements.name === "init")) {
                        return undefined;
                    }

                    return GenerateArray.generateRandomNumsNonRepeating.bind(undefined, gameTemplates.numberOfElements)
                }

Позже у меня есть функция init, которая получает все функции init и затем инициализирует их. Проблема в том, что я не смог придумать способ сделать while l oop декларативным способом и просто сделал функцию repeatWhile, которая использует while l oop. Проблема в том, что для того, чтобы отделить чистую функцию и функцию, которая изменяет состояние объекта в дополнение к наличию отдельного входа для проверки. Это заставляет функцию repeatWhile принимать 5 аргументов, а чистая функция имеет присваивание и более сложный вывод. Есть ли у вас какие-либо идеи, чтобы сделать код более простым и пригодным для повторного использования? Спасибо.

Вот код:

function init(obj) {
        function getInitArr(obj) {//this function works and does not seem to need checking
            function getModifiedArray(prop) {
                function getTypeOfProp(prop) {
                    return [
                        function object(prop) {return typeof prop === "object" && prop.genObj === 0},
                        function initFunction(prop) {return prop instanceof Function && prop.name === "init"},
                        function normal() {return true}
                        ]
                        .find(a=>a(prop)).name;
                }

                const getModifiedArrayByType = {
                    object: function (prop) {
                        return getInitArr(obj[prop])
                    },
                    initFunction: function (prop) {
                        return [[obj, prop, obj[prop]]]
                    },
                    normal: function () {
                        return []
                    }
                };

                return getModifiedArrayByType[getTypeOfProp(obj[prop])](prop);
            }

            return Object.keys(obj)
                .reduce((arr,prop)=>[...arr, ...getModifiedArray(prop)], [])
        }

        function initProperties() {
            const getIndicesIfNotUndefined = (a, objPropFn, i) => {
                if (objPropFn[2]() !== undefined) {
                    return [...a, i];
                }

                return a;
            };

            function getAllExceptResetOnes(toCheck) {
                return (a, i) => !(toCheck.includes(i));
            }

            return function (input) {
                let toCheck = input
                    .reduce(getIndicesIfNotUndefined, []);

                return [
                    input.filter(getAllExceptResetOnes(toCheck)),
                    // toCheck
                    //     .reduce((acc, index) => {
                    //         acc.splice(acc[acc.length - 1], 1, ...input.slice(acc[acc.length - 1] + 1, index));
                    //         return acc;
                    //     }, []),
                    toCheck,
                    [input, toCheck]
                ]
            };
        }

        function initializeProperties([input, toCheck]) {
            toCheck
                .forEach(index => {
                    input[index][0][input[index][1]] = input[index][2]();
                });
        }

        repeatWhile(
            initProperties(),
            resToCheck=>resToCheck.length>0,
            getInitArr(obj),
            initializeProperties
        );

        function repeatWhile (fn, condition, input, actionOnSeparateOutput = x=>x, inputToCheck = input) {
            let separateOutput;
            while (condition(inputToCheck)) {
                [input, inputToCheck = input, separateOutput = input] = fn(input);
                actionOnSeparateOutput(separateOutput);
            }
            return input;
        }
    }
...