var f = function() {
  this.x = 5;
  (function() {
    this.x = 3;
  })();
  console.log(this.x);
};
f.call(f);
f();
f.call();
var f = function() {
  this.x = 5;
  (function() {
    this.x = 3;
  })();
  console.log(this.x);
};
f.call(f);
f();
f.call(); Во первых вы вызываете функцию. И внутри этой функции функция сама т.е. 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 объект window. По данным МДН
thisArg
Необязательный. Значение этого предусмотрено для вызова функции. Обратите внимание, что это может не быть фактическим значением, видимым методом: если метод является функцией в нестрогом режиме, нулевые и неопределенные будут заменены глобальным объектом, а примитивные значения будут преобразованы в объекты.
Смотрите ниже фрагмент.
function foo(){
  console.log(this);
}
foo.call(foo); //foo function
foo.call(); //window object Если нет определенного контекста, this будет window. Ваша внутренняя функция всегда запускается без контекста, поэтому она установит для window.x значение 3. Если вы window.x f(), она также будет работать с this существующим window поэтому записывает 3.
 Однако если вы выполните f.call(f), this будет объект функции f, а для свойства x будет установлено значение 5.
  f.call(f)
  console.log(
    f.x, // 5
    window.x // 3
  );
Я бы порекомендовал пройти через это с помощью отладчика, если это еще не ясно.
 Когда вы вызываете 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("---------------")В дополнение к другим ответам, если вы хотите предсказуемое поведение, у вас есть по крайней мере 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
Ключевое слово this ссылается на объект контекста, в котором выполняется текущий код. Вне любой функции это относится к глобальному объекту.
 Используя функции call(), apply() значение этого может передаваться из одного контекста в другой контекст.
this.x первый аргумент как f, this.x ссылается на 5. Таким образом, ответ печатается как 5.this, как 3. Таким образом, он печатает как 3.3 в качестве вывода.