Кажется достаточно простым, я хочу вызвать функцию с массивом аргументов. Конечно, я могу сказать func.apply(this, ['some', 'arguments']);, но это изменит значение this внутри func. Есть идеи, как это сделать, не меняя его?
В Javascript есть эквивалент .apply, который не меняет значение this?
Ответы (5)
Вы не можете этого сделать, из-за того, как this работает в JavaScript. Читай дальше:
Следуя разделу "Ввод контекста выполнения" спецификации ECMAScript: когда вы вызываете функцию, значение this определяется тем, что находится слева от него (так называемым объектом активации) . Давайте создадим функцию по имени Стив и поместим ее в объект:
function steve(){}
var obj = { method: steve };
…когда мы называем Стива obj.method(), его this — это obj, потому что obj был объектом активации.
Сложный случай — когда ничего не находится слева от вызова функции:
steve(); // Who am I ?!
Слева от вызова функции нет ничего — по сути, это null — поэтому значение this устанавливается на значение по умолчанию глобального объекта (window в веб-браузерах, global в Node.js и т. д.) .).
Таким образом, вы фактически устанавливаете this функции каждый раз, когда вызываете ее.
P.S. вызов steve.apply(null, []) эквивалентен вызову steve().
steve.apply(undefined, []) и steve() эквивалентны, хотя их поведение в ES3 и ES5 различается.
- person gsnedders; 09.03.2011
this к глобальному объекту, и null/undefined эквивалентны. Можете ли вы показать мне, где описано новое поведение?
- person s4y; 09.03.2011
this, которое она получает во время вызова. this по-прежнему будет тем, что вы передали .bind().
- person s4y; 04.05.2017
Обратите внимание, что в ES6 вы также можете написать:
func(...someArray)
Здесь this становится Window внутри func, что бесполезно. Но если вы напишете:
obj.func(...someArray)
this внутри func будет obj.
Возможно, это именно та функция, которую я искал 5 лет назад, но это было 5 лет назад, так что кто помнит :)
Значение 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, []);
Если вы вызываете одну функцию, передайте null.
func.apply(null, ['some', 'arguments']);
Если вы вызываете функцию, которая является методом объекта, передайте этот объект.
var arr = [];
arr.push.apply(arr, ['some', 'arguments']);
Чтобы соответствовать тому, как работает это.
То, что вы хотите, не имеет особого смысла.
В стандарте ecmascript this определяется следующим образом:
11.1.1 Ключевое слово this Ключевое слово this оценивается как значение ThisBinding текущего контекста выполнения.
Разрешение thisBinding для контекста выполнения функции указывается следующим образом:
10.4.3 Ввод кода функции Следующие шаги выполняются, когда элемент управления входит в контекст выполнения для кода функции, содержащегося в объекте функции F, вызывающая сторона предоставила thisArg, а вызывающая сторона предоставила аргументыList:
- Если код функции является строгим, задайте для ThisBinding значение thisArg.
- В противном случае, если thisArg имеет значение NULL или не определено, установите для ThisBinding глобальный объект.
- В противном случае, если Type(thisArg) не является Object, задайте для ThisBinding значение ToObject(thisArg).
- В противном случае установите для ThisBinding значение thisArg.
- Пусть localEnv будет результатом вызова NewDeclarativeEnvironment, передающего значение внутреннего свойства [[Scope]] F в качестве аргумента.
- Установите для LexicalEnvironment значение localEnv.
- Установите для VariableEnvironment значение localEnv.
- Пусть code будет значением внутреннего свойства F [[Code]].
- Выполните создание экземпляра привязки объявления, используя код кода функции и список аргументов, как описано в 10.5.
Другими словами: либо вы указываете его, либо он автоматически присваивается глобальному объекту. Он никогда не унаследует привязку this от своей родительской области, поэтому единственный способ передать thisBindiong родительской области своим дочерним элементам - это либо
- сохраните его в локальной переменной в родительской области, например var
self = this - введите его с помощью вызова/применения, как код, который вы указали в своем вопросе.
nullв качестве первого аргумента. Однако на что должно ссылатьсяthisвнутриfunc? - person jAndy   schedule 09.03.2011thisвнутри функции таким образом, что его нельзя использовать. - person Lightness Races in Orbit   schedule 09.03.2011.apply(). Я предполагал, что функция будет каким-то образом привязана к своему объекту, поэтому не хотел ее менять, как это делает apply, но видимо такой связи нет иapply()просто имеет дело с функцией, которую она вызывает. - person JussiR   schedule 10.03.2011