Странная область видимости класса JavaScript

Предполагая, что у меня есть два файла. Один файл с классом, где метод hello просто console.infos this:

// Class.js
class Test {
  constructor() {
    this.inside = true;
  }

  hello() {
    console.info('inside hello')
    console.info(this);
  }
}

module.exports = new Test();

и еще один файл, который выполняет метод hello этого класса:

// index.js
const Test = require('./Class.js');

Test.hello();
// -> 'inside hello'
// -> { inside: true } 

Все работает как положено, this в методе hello() имеет правильный прицел. Но, когда я создаю новый экземпляр класса и экспортирую простоhello этого нового экземпляра:

// Class.js
class Test {
  constructor() {
    this.inside = true;
  }

  hello() {
    console.info('inside hello')
    console.info(this);
  }
}

module.exports = (new Test()).hello; // <- just hello is exported

затем область видимости hello() изменилась, и кажется, что он больше не является частью класса:

// index.js
const hello = require('./index.js');

hello();
// -> 'inside hello'
// -> undefined

Есть ли причина, по которой эта единственная экспортируемая функция действует так по-разному?


Я пробовал это на Python, и это сработало (может быть, и на других языках):

# Class.py
class Class:
  def __init__(self):
    self.test = 'hello'

  def hello(self):
    print('inside hello')
    print(self)

hello = Class().hello


# index.py
from Class import hello

hello()
# -> 'inside hello'
# -> <Class.Class instance at 0x10e26e488>
this всегда является объектом, для которого вызывается функция. Вы вызываете hello напрямую, поэтому this не определен.
t.niese 27.04.2018 09:24

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

Muhammad Usman 27.04.2018 09:24

В отличие от большинства языков, this в Javascript не передается с методами, .. В простейшей форме, если вы не используете . (точка) для вызова своей функции, Javascript не может узнать этот контекст, .. Это было привязка / вызов и т. д. вступают в игру.

Keith 27.04.2018 09:25

Возможный дубликат Как работает ключевое слово "это"?

t.niese 27.04.2018 09:26

здесь есть специфика NodeJ, в браузере контекстом был бы глобальный this, то есть window. Узел ведет себя по-разному с точки зрения глобального материала. Кроме того, this в JS исходит из контекста выполнения, а не из создания, это зависит от того, где он вызван, если не привязан

Kaddath 27.04.2018 09:30
Поведение ключевого слова "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) для оценки ваших знаний,...
2
5
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Когда вы вызываете hello() в автономном режиме, у него нет контекста вызова - он не вызывается из объекта, когда указанный объект обычно будет контекстом его вызова. (например, Test.hello(); - контекст вызова будет Test в этой строке)

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

const test = new Test();
module.exports = test.hello.bind(test);

У них разный контекст:
В первом случае "hello" привязывается к объекту "Test". Во втором «hello» привязывается к «global scope», которая равна «undefined» .
Если вы запустите второй в веб-браузере, вы получите объект «окно», который является глобальным контекстом в браузере.

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