Кажется, достаточно легко, я хочу вызвать функцию с массивом аргументов. Конечно, я могу сказать func.apply(this, ['some', 'arguments']);
, но это изменит значение this
внутри func
. Любая идея, как это сделать, не меняя его?
В Javascript есть эквивалент .apply, который не меняет значение этого?
Ответ 1
Обратите внимание, что в ES6 вы также можете написать:
func(...someArray)
Здесь this
становится Window
внутри func
, что бесполезно. Но если вы пишете:
obj.func(...someArray)
this
внутри func
будет obj
.
Это может быть особенностью, которую я искал 5 лет назад, но это было 5 лет назад, поэтому кто помнит:)
Ответ 2
Вы не можете, из-за того, как this
работает в JavaScript. Читайте дальше:
Переход по "Ввод контекста выполнения" в спецификации ECMAScript: при вызове функции значение this
равно определяется тем, что ему осталось (называется объектом активации). Позвольте создать функцию под названием steve и поместить его в объект:
function steve(){}
var obj = { method: steve };
... когда мы называем steve как obj.method()
, его this
составляет obj
, потому что obj
был объектом активации.
Трудный случай - когда ничего не осталось слева от вызова функции:
steve(); // Who am I ?!
Нет ничего слева от вызова функции - эффективно, это null
- поэтому значение this
установлено на значение по умолчанию для глобального объекта (window
в веб-браузерах, global
в Node.js и т.д.).
Таким образом, вы на самом деле устанавливаете функцию this
каждый раз, когда вы ее вызываете.
P.S. вызов steve.apply(null, [])
эквивалентен вызову steve()
.
Ответ 3
Значение this
не является тайной при вызове функции в зависимости от того, как она называется "нормально" (без call
или apply
):
func(); // `this` is the global object, or undefined in ES5 strict mode
obj.func(); // `this` is `obj`
Итак, чтобы избежать "изменения" значения this
, просто передайте правильное значение apply
, в зависимости от того, как вы бы назвали его "нормально":
func.apply(undefined, []); // global object, or undefined in ES5 strict mode
obj.func.apply(obj, []);
Ответ 4
Если вы вызываете только одну функцию, пройдите null
.
func.apply(null, ['some', 'arguments']);
Если вы вызываете функцию, являющуюся методом объекта, передайте этот объект.
var arr = [];
arr.push.apply(arr, ['some', 'arguments']);
Чтобы соответствовать тому, как работает this,
Ответ 5
То, что вы хотите, не имеет большого смысла.
В стандарте ecmascript this
определяется следующим образом:
11.1.1 Это ключевое слово. Это ключевое слово оценивает значение ThisBinding текущего исполнения контекст.
Это определение привязки для контекста выполнения функций задается следующим образом:
10.4.3 Ввод кода функции Следующие шаги выполняются, когда управление входит в контекст выполнения для кода функции, содержащегося в функциональный объект F, предоставленный вызывающий thisArg, и вызывающий Список аргументов:
- Если код функции является строгим кодом, установите значение ThisBinding для thisArg.
- Если значение thisArg равно null или undefined, установите значение ThisBinding для глобальный объект.
- Если тип (thisArg) не является объектом, установите для параметра ThisBinding значение ToObject (thisArg).
- Else задайте значение ThisBinding для этогоArg.
- Пусть localEnv является результатом вызова NewDeclarativeEnvironment передавая значение [[Область]] внутреннее свойство F как аргумент.
- Установите для LexicalEnvironment значение localEnv.
- Задайте переменную окружения localEnv.
- Пусть код является значением внутреннего свойства Fs [[Code]].
- Выполнение обязательного связывания с использованием кода функции code и argumentList, как описано в 10.5.
Другими словами: либо вы указываете его, либо автоматически устанавливаете глобальный объект. Он никогда не будет наследовать эту привязку из его родительской области, поэтому единственный способ предоставить этому родительскому объекту thisBindiong родительской области - это либо
- сохранить его в локальной переменной в родительской области, например var
self = this
- вводить его вызовом/применять как код, который вы указали в своем вопросе.