Привязка «этого»

Я изучаю, как значение this связывается в JavaScript. В следующем примере правильно ли сказать, что «это» связывается с методом getFriends() вместо объекта «детали», что является причиной того, что this.name = «» вместо this.name = «Джо»?

const details = {
    name: 'Joe',
    friends: [ 'Bob', 'Alex' ],
    getFriends: function() {
        this.friends.forEach( function( friend ) {
            console.info( this.name + " is friends with " + friend );
        } );
    }
};

details.getFriends();

// Output:
// is friends with Bob
// is friends with Alex

Насколько я понял из своих исследований, «это» не привязывает ни на один уровень вверх в родительской области, верно? Это одно из преимуществ использования стрелочных функций, которые связывают this с родительской областью.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
126
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Нет, когда вы запускаете код таким образом, this указывает на глобальный объект окна. Вы можете console.info значение this. Чтобы проверить это, вы также можете поместить ключ my_name в окно (не используйте имя, так как оно используется окном). Теперь, когда вы запустите код, вы увидите глобальное:

const details = {
    my_name: 'Joe',
    friends: [ 'Bob', 'Alex' ],
    getFriends: function() {
        this.friends.forEach( function( friend ) {
            console.info( this.my_name + " is friends with " + friend );
        } );
    }
};
window.my_name = "What?"
details.getFriends();

К вашему сведению: forEach принимает второе значение, которое вы можете использовать, чтобы указать, что this будет в обратном вызове. Так это работает, например:

const details = {
    my_name: 'Joe',
    friends: [ 'Bob', 'Alex' ],
    getFriends: function() {
        this.friends.forEach( function( friend ) {
            console.info( this.my_name + " is friends with " + friend );
        }, this ); //<-- pass this into the forEach
    }
};

details.getFriends();

Конечно, вы всегда можете использовать функцию стрелки.

Ответ принят как подходящий

Цитата из w3schools

In a method, this refers to the owner object. Alone, this refers to the global object. In a function, this refers to the global object. In a function, in strict mode, this is undefined. In an event, this refers to the element that received the event. Methods like call(), and apply() can refer this to any object.

https://www.w3schools.com/js/js_this.asp

Отличный ответ. Эта цитата действительно хорошо объясняет все различные привязки ключевого слова «этот». Спасибо за помощь! :)

GTS Joe 16.05.2019 00:14

Ключевое слово this относится к контексту выполнения ток.

По умолчанию this в функции установлен в глобальный контекст, который всегда является объектом окна в браузере:

function foo() {
  return this;
}

console.assert(foo() === window);

Однако при вызове в качестве конструктора оператор new устанавливает this объект, созданный из прототипа функции. Этот контекст уникален для каждого экземпляра.

function foo() {
  return this;
}

console.assert(new foo() !== window);
console.assert(new foo() !== new foo());

Когда у объекта есть метод, this в этом методе по умолчанию является этим объектом:

const question = {
  ask: function () {
    return this;
  }
};

console.assert(question.ask() === question);

Теперь вот почему важен контекст выполнения ток.

Если вы возьмете этот метод за пределы его объекта, тогда этот контекст метода по умолчанию будет глобальным контекстом:

const question = {
  ask: function () {
    return this;
  }
};

const ask = question.ask;

console.assert(ask() === window);

Чтобы решить эту проблему, вы можете использовать bind, call или apply:

const question = {
  ask: function () {
    return this;
  }
};

const ask = question.ask;

console.assert(ask.bind(question)() === question);
console.assert(ask.call(question) === question);
console.assert(ask.apply(question) === question);

Вы, должно быть, слышали о стрелочных функциях, которые привязывают this к контексту, который был доступен во время определения функции.

Раньше нам приходилось сохранять this в переменной (обычно называемой that), чтобы ссылаться на правильный контекст. (Или используйте bind.)

function foo() {
  const that = this;
  // By the time the function executes, the execution context
  // will be different even though we invoked the function
  // as a constructor.
  setTimeout(function () {
    console.assert(that !== this);
    console.assert(this === window);
  }, 100);
}

new foo();

Эта техника устарела с функциями стрелок:

function foo() {
  setTimeout(() => {
    console.assert(this !== window);
  }, 100);
}

new foo();

Однако помните, что функции имеют лексическую область видимости, поэтому нет даст вам ожидаемый результат:

const question = {
  ask: () => {
    return this;
  }
};

console.assert(question.ask() === window);

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

Другие вопросы по теме