JavaScript - применить вызов функции к объекту с другим прототипом

1

Задача (на самом деле проблема), с которой я сталкиваюсь, заключается в следующем. У меня есть массив (давайте назовем его arr). Первый элемент массива - это функция, а остальные - аргументы. Например:

arr = [(a, b) => a + b, 5, 7];

Поэтому мне нужно вызвать функцию (a, b) => a + b с аргументами 5 и 7. Тем не менее, я не хочу использовать arr[0](...arr.slice(1)), вместо этого я хочу сделать это, используя Function.prototype.apply и Function.prototype.call (я также могу использовать Function.prototype.bind если необходимо). Таким образом, в принципе, я могу получить доступ к arr только один раз, и никакие другие переменные не могут быть использованы. Кроме того, мне не разрешено изменять свойства arr или его или хранить какие-либо другие данные где-то (например, как свойство какого-либо глобального объекта и т.д.). Возможно ли это?

Моя попытка

Я попытался понять это, и это то, что я придумал (это не работает):

Function.prototype.apply.call(this, ...arr);

Однако это вызывает ошибку:

Uncaught TypeError: Function.prototype.apply вызывается в #Global, который является объектом, а не функцией

Вопрос

Каков правильный способ сделать это?

  • 0
    Как вы думаете, this относится к вашему примеру? Следующее будет работать: Function.prototype.call(...arr) .
  • 0
    @FelixKling. Извините, я удалил вопрос случайно. Ну, ваш пример не возвращает 12 как ожидалось, но вместо этого он возвращает undefined .
Показать ещё 4 комментария
Теги:
function
prototype
ecmascript-7

2 ответа

-5
Лучший ответ

Вы можете использовать деструктурирование, чтобы получить элементы массива arr качестве переменных, затем вызвать функцию с индексом 0 с элементами в индексах 1-N

let arr = [(a, b) => a + b, 5, 7];
let [fn, a, b] = arr;
console.log(fn(a, b));

Для любого количества элементов в индексах 1-N вы можете использовать элемент отдыха

let arr = [(a, b) => a + b, 5, 7];
let [fn, ...rest] = arr;
console.log(fn.apply(null, rest));

В качестве альтернативы, используя Function, литерал шаблона для преобразования массива в строку, .replace() с RegExp /\s/g с .replace() для удаления пробелов, .match() с RegExp /(\(.*\)=>[^,]+(?=,))|[^,]{1}[^\1]+/g для захвата функции стрелки, отрицать первую запятую символов, которые не являются функцией стрелки и функцией стрелок, захваченной в первой группе, мы можем ссылаться на arr один раз и не создавать дополнительные переменные, сохраняя для сразу вызываемых функций функции стрелки

let arr = [(a, b) => a + b, 5, 7];

console.log(
  (([a, b]) => new Function('return (${a})(${b.split(/,/)})')())
  ('${arr}'.replace(/\s/g, "").match(/(\(.*\)=>[^,]+(?=,))|[^,]{1}[^\1]+/g))
)
  • 0
    Я знаю о деструктуризации, но об этом я сейчас точно и спрашиваю. Но в любом случае, как объяснили другие пользователи, я начинаю верить, что не существует встроенного метода для выполнения того, что я хочу.
  • 0
    @ user_guest_333 Что вы подразумеваете под "встроенным"? Чего ты пытаешься достичь?
Показать ещё 5 комментариев
2

вместо этого я хочу сделать это, используя Function.prototype.apply и Function.prototype.call. Возможно ли это?

Конечно, но мы должны повторить arr:

arr[0].call(...arr)

Живой пример:

const arr = [(a, b) => a + b, 5, 7];
console.log(arr[0].call(...arr));

Это не будет работать, если функция требуется определенное this, но ваша функция не делает, по двум причинам, либо из которых были бы достаточно: 1. функции стрелки, так что это не важно, что this мы называем его, он закрывается над тем, где он был создан; и 2. Он все равно не использует this.

Тем не менее, возможно, лучше просто дать себе вспомогательную функцию, которая делает это вместо этого.

  • 0
    Что делать , если this аргумент имеет право быть arr себе? Это возможно без нарезки?
  • 0
    @ user_guest_333: Дох! Конечно, потому что с функцией стрелки thisArg любом случае не используется. Но мы все равно должны повторить arr . Исправлена.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню