вызов () функции в своем собственном контексте - PullRequest
22 голосов
/ 06 мая 2019

var f = function() {
  this.x = 5;
  (function() {
    this.x = 3;
  })();
  console.log(this.x);
};

f.call(f);

f();

f.call();

Запуск var f при f.call(f) выходах 5.Когда он работает как f() или f.call() вывод 3.

Что происходит в каждом случае?На что ссылается внутренняя функция this?

Ответы [ 5 ]

14 голосов
/ 06 мая 2019

Первый случай:

Во первых вы вызываете функцию. А внутри функции сама функция, т.е. f установлена ​​как this. Таким образом, в первом примере this.x = 5; устанавливает свойство x для функции.

Когда внутренняя функция вызывается this относится к window объекту, поэтому this.x = 3; изменяет свойство x объекта окна.

Когда он регистрирует console.log(this.x);, здесь регистрируется то же свойство x, которое было установлено как свойство функции.

Второй случай:

Во втором примере this внутри внешней функции относится к window, поэтому при оценке this.x = 3; window.x становится 3. Как this относится к window во внешней функции, так console.log(this.x); logs window.x, что 3

Вывод:

Вывод всего обсуждения заключается в том, что если аргумент call() не передается, тогда объект window автоматически связывается. Согласно MDN

thisArg

Необязательный. Значение этого предусмотрено для вызова функции. Обратите внимание, что это может не быть фактическим значением, видимым методом: если метод является функцией в нестрогом режиме, null и undefined будут заменены глобальным объектом , а примитивные значения будут преобразованы в объекты .

См. Фрагмент ниже.

function foo(){
  console.log(this);
}
foo.call(foo); //foo function
foo.call(); //window object
6 голосов
/ 06 мая 2019

Если нет определенного контекста, this будет window. Ваша внутренняя функция всегда запускается без контекста, поэтому она установит window.x в 3. Если вы вызовете f(), она также будет работать с this, равным window, следовательно, регистрируя 3.

Однако, если вы сделаете f.call(f), this будет функциональным объектом f, а его свойство x будет установлено в 5.

  f.call(f)
  console.log(
    f.x, // 5
    window.x // 3
  );

Я бы порекомендовал пройти через него с помощью отладчика , если пока не ясно.

2 голосов
/ 06 мая 2019

Когда вы вызываете f со ссылкой на себя, он устанавливает для свойства x значение 5, а внутренняя анонимная функция имеет значение this, относящееся к окну, поэтому для window.x устанавливается значение 3 За пределами анонимной функции this по-прежнему ссылается на функцию f, поэтому console.log (this.x) выводит 5.

Когда вы вызываете f, используя f() или f.call(), функция f и анонимная функция внутри нее имеют ссылку this, установленную на window (по умолчанию), и, таким образом, изменяют значение this.x внутри или вне анонимной функции влияет на результат вывода.

Это можно ясно увидеть, если вы console.log о значениях this внутри функции f и внутри внутренней анонимной функции.

var f = function() {
	console.log("This inside function f:", this.toString());
  this.x = 5;
  (function() {
	  console.log("This inside anonymous inner function:", this.toString());
    this.x = 3;
  })();
  console.log(this.x);
};
console.log("calling function x with this set to itself");
f.call(f);
console.log("---------------")
console.log("invoking function x with brackets ()")
f();
console.log("---------------")
console.log("calling function x without setting this context")
f.call();
console.log("---------------")
1 голос
/ 07 мая 2019

В дополнение к другим ответам, если вы хотите предсказуемое поведение, у вас есть по крайней мере 2 метода, доступных для вас.

Метод 1: (закрытие)

var f = function() {
  this.x = 5;
  var that = this;
  (function() {
    that.x = 3;
  })();
  console.log(this.x);
};

f.call(f); // 3

f(); // 3

f.call(); // 3

Метод 2: (функция стрелки)

var f = () => {
  this.x = 5;
  (function() {
    this.x = 3;
  })();
  console.log(this.x);
};

f.call(f); // 3

f(); // 3

f.call(); // 3
0 голосов
/ 27 мая 2019

Ключевое слово 'this' относится к объекту контекста, в котором выполняется текущий код. Вне любой функции это относится к глобальному объекту.

При использовании функций call(), apply() значение этого может передаваться из одного контекста в другой контекст.

  • Таким образом, в 1-м случае [ f.call (f) ] путем вызова функции вызова и давая первый аргумент как f, this.x относится к 5. Таким образом, ответ печатается как 5.
  • 2-й случай [ f () ] это вызов функции без использования вызова функция. Так он ссылается на контекст выполнения this как 3. Так что печатает как 3.
  • В третьем случае [ f.call () ], внутри функции вызова нет аргумент упоминается. Так что это относится к глобальному объекту и печатает 3 в качестве вывода.
...