Задача (на самом деле проблема), с которой я сталкиваюсь, заключается в следующем. У меня есть массив (давайте назовем его 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, который является объектом, а не функцией
Каков правильный способ сделать это?
Вы можете использовать деструктурирование, чтобы получить элементы массива 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))
)
вместо этого я хочу сделать это, используя 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
.
Тем не менее, возможно, лучше просто дать себе вспомогательную функцию, которая делает это вместо этого.
this
аргумент имеет право быть arr
себе? Это возможно без нарезки?
thisArg
любом случае не используется. Но мы все равно должны повторить arr
. Исправлена.
this
относится к вашему примеру? Следующее будет работать:Function.prototype.call(...arr)
.12
как ожидалось, но вместо этого он возвращаетundefined
.