Стрелочная функция ES6: почему это указывает по-разному при использовании в конструкторе и объектном литерале?

Я знаю, что стрелочные функции наследуют this от объемлющей области. Тем не менее, до сих пор не могу понять, почему this в стрелочной функции, определенной в литерале объекта, указывает на глобальный объект, а в конструкторе на созданный объект. Рассмотрим следующий код:

function Obj() {
  this.show = () => {
    console.log(this);
  };
}
const o = new Obj();
const o2 = {
  show: () => {
    console.log(this);
  }
}

o.show(); // o
o2.show() // window || undefinded

person Kuba Sułkowski    schedule 19.04.2020    source источник
comment
Отвечает ли это на ваш вопрос? Самоссылки в литералах/инициализаторах объектов   -  person VLAZ    schedule 19.04.2020


Ответы (3)


function Obj() {
  this.show = () => {
    console.log(this);
  };
}
const o = new Obj();
o.show(); 

Здесь «это» работает на основе правил ключевого слова «новое», указывая на новый объект со структурой, определенной внутри Obj() (новый объект является контекстом). Дополнительные сведения см. по адресу: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

const o2 = {
  show: () => {
    console.log(this);
  }
}
o2.show() // window || undefinded

Здесь «это» получает свое значение во время выполнения, и поскольку ни лямбда-функции, ни литералы объектов не определяют контекст, оставшийся контекст является глобальным, и поэтому вы получаете это значение.

person Beto Rodriguez    schedule 19.04.2020

Хорошо, нашел ответ, как указано в «Секретах javascript-ниндзя»:

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

Итак, внутри функции конструктора this === {}. В то время как при определении литерала объекта this по-прежнему указывает на глобальный объект или undefined в строгом режиме.

person Kuba Sułkowski    schedule 19.04.2020

Это потому, что во время объявления Object еще не инициализирован. Вы можете принудительно выполнить инициализацию, используя немедленно вызываемое функциональное выражение (IIFFE). или используйте Object.create. Что-то типа:

// IIFE
const x = (() => ({a: 1, b: 2, sum() {return this.a + this.b}}))();
console.log(`x.sum() => ${x.sum()}`);
// Object.create
const y = Object.create({a:1, b:2, sum() {return this.a + this.b}});
console.log(`y.sum() => ${y.sum()}`);

person KooiInc    schedule 19.04.2020