Обертывание функции с необязательными позиционными аргументами - PullRequest
0 голосов
/ 03 мая 2020

Я хочу написать оболочку для метода страницы сегмента , где он будет принимать вызываемые аргументы и объединять мой набор параметров с переданными параметрами, а также передавать полученные параметры вместе с другими аргументами. в page и вызывая его.

Наивный способ написать это:

analytics.page = () => {
  const options = {
    ...arguments[3],
    "mydefault": "options",
  }
  analytics.page(arguments[0], arguments[1], arguments[2], options, arguments[4]);
}

Проблема в том, что все аргументы page являются позиционными и необязательными. Кроме того, аргументы обрабатываются по-разному в зависимости от количества передаваемых вами аргументов. Т. Е. Если указан только один аргумент, аргумент обрабатывается как name, а не category.

analytics.page("im a category", "im a name");
analytics.page("im a name now");

Есть ли чистый способ справиться с этими случаями, или мне нужно написать кучу условных проверок длины объекта arguments - по сути, реплицируя, как page внутренне анализирует аргументы?

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Вы должны определить, какой переданный аргумент, если есть, является опциями. К счастью, это не так сложно: если передан аргумент options, он будет объектом, а не функцией, и будет следовать за другим объектом. Перебирайте аргументы, начиная с первого. Если обнаружен нефункциональный объект, установите флаг. Если найден другой нефункциональный объект, это options - измените его при необходимости. В противном случае вам нужно вставить параметры по умолчанию в правильную позицию, что можно сделать, проверив, является ли последний аргумент функцией или нет:

const changeOptions = (...args) => {
  const defaultOptions = { "mydefault": "options" };
  let propertiesArgFound = false;
  for (const [index, arg] of args.entries()) {
    if (typeof arg === 'object') {
      if (propertiesArgFound) {
        // This is the options object, mutate it:
        args[index] = { ...defaultOptions, ...arg };
        return args;
      } else {
        propertiesArgFound = true;
      }
    }
  }
  // Options object was not found, add it to the argument list
  // either at the last position, or at the next-to-last position:
  if (typeof args[args.length - 1] === 'function') {
    args.splice(args.length - 1, 0, defaultOptions)
  } else {
    args.push(defaultOptions);
  }
  return args;
};
const analyticsPage = (...args) => {
  const newArgs = changeOptions(...args);
  // analytics.page(newArgs);
  console.log(newArgs);
};

analyticsPage('foo', 'bar', { property: 'baz' });
analyticsPage('foo', 'bar', { property: 'baz' }, { someOption: 'option' });
analyticsPage('foo', 'bar', () => 'callback');
0 голосов
/ 03 мая 2020

Прежде всего, в вашем коде в целом есть две проблемы:

  1. не может использовать arguments top получить аргументы, переданные функции стрелки, поэтому вам нужно используйте обычную функцию для этого. Или определите аргументы самостоятельно, например, ...args.

  2. analytics.page(arguments[0], arguments[1], arguments[2], options, arguments[4]); создаст бесконечную рекурсию, потому что она вызовет вашу функцию стрелки, а не исходную.

Таким образом, вам нужно сохранить исходную функцию page и переслать измененный список аргументов, используя, например, MDN Function.prototype.apply () , если вам нужно применить или нет, зависит от если исходная функция page использует this для обозначения analytics или нет.

let analytics = {
   page() {
        console.dir(arguments)
   }
}

let orgPage = analytics.page
analytics.page = function() {

  // in case that the fourth parameter with your option is optional.
  if( arguments.length > 3 ) {
    const options = {
      ...arguments[3],
      "mydefault": "options",
    }

    arguments[3] = options;
  }

  return orgPage.apply(analytics, arguments)
}

analytics.page(1,2, 3,{foo: 1, bar: 1}, 5)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...