Bezdepbonusu7Программирование: статьи и ответы

Вопрос

В Javascript есть эквивалент .apply, который не меняет значение this?

Автор вопроса: JussiRОтветов: 5

Кажется достаточно простым, я хочу вызвать функцию с массивом аргументов. Конечно, я могу сказать func.apply(this, ['some', 'arguments']);, но это изменит значение this внутри func. Есть идеи, как это сделать, не меняя его?

  • Ну, вы можете передать null в качестве первого аргумента. Однако на что должно ссылаться this внутри func ? jAndy 09.03.2011
  • Вопрос недостаточно ясен. Пожалуйста, дайте больше кода. artyom.stv 09.03.2011
  • Похоже, вы используете this внутри функции таким образом, что его нельзя использовать. Lightness Races in Orbit 09.03.2011
  • Хорошо, теперь я понял. В моем случае у меня был прототип функции объекта, который я хотел вызвать с помощью .apply(). Я предполагал, что функция будет каким-то образом привязана к своему объекту, поэтому не хотел ее менять, как это делает apply, но видимо такой связи нет и apply() просто имеет дело с функцией, которую она вызывает. JussiR 10.03.2011

javascriptargumentsfunctionapply

Ответы

Ответ 1 · рейтинг 30 · s4y

Вы не можете этого сделать, из-за того, как 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().

Ответ 2 · рейтинг 15 · JussiR

Обратите внимание, что в ES6 вы также можете написать:

func(...someArray)

Здесь this становится Window внутри func, что бесполезно. Но если вы напишете:

obj.func(...someArray)

this внутри func будет obj.

Возможно, это именно та функция, которую я искал 5 лет назад, но это было 5 лет назад, так что кто помнит :)

Ответ 3 · рейтинг 4 · David Tang

Значение 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 · рейтинг 2 · Thai

Если вы вызываете одну функцию, передайте null.

func.apply(null, ['some', 'arguments']);

Если вы вызываете функцию, которая является методом объекта, передайте этот объект.

var arr = [];
arr.push.apply(arr, ['some', 'arguments']);

Чтобы соответствовать тому, как работает это.

Ответ 5 · Martin Jespersen

То, что вы хотите, не имеет особого смысла.

В стандарте ecmascript this определяется следующим образом:

11.1.1 Ключевое слово this Ключевое слово this оценивается как значение ThisBinding текущего контекста выполнения.

Разрешение thisBinding для контекста выполнения функции указывается следующим образом:

10.4.3 Ввод кода функции Следующие шаги выполняются, когда элемент управления входит в контекст выполнения для кода функции, содержащегося в объекте функции F, вызывающая сторона предоставила thisArg, а вызывающая сторона предоставила аргументыList:

  1. Если код функции является строгим, задайте для ThisBinding значение thisArg.
  2. В противном случае, если thisArg имеет значение NULL или не определено, установите для ThisBinding глобальный объект.
  3. В противном случае, если Type(thisArg) не является Object, задайте для ThisBinding значение ToObject(thisArg).
  4. В противном случае установите для ThisBinding значение thisArg.
  5. Пусть localEnv будет результатом вызова NewDeclarativeEnvironment, передающего значение внутреннего свойства [[Scope]] F в качестве аргумента.
  6. Установите для LexicalEnvironment значение localEnv.
  7. Установите для VariableEnvironment значение localEnv.
  8. Пусть code будет значением внутреннего свойства F [[Code]].
  9. Выполните создание экземпляра привязки объявления, используя код кода функции и список аргументов, как описано в 10.5.

Другими словами: либо вы указываете его, либо он автоматически присваивается глобальному объекту. Он никогда не унаследует привязку this от своей родительской области, поэтому единственный способ передать thisBindiong родительской области своим дочерним элементам - это либо

  1. сохраните его в локальной переменной в родительской области, например var self = this
  2. введите его с помощью вызова/применения, как код, который вы указали в своем вопросе.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы