Как стать автором
Поиск
Написать публикацию
Обновить
Криптонит
Разрабатываем. Исследуем. Просвещаем

На картинке — код на JavaScript с ошибкой, который написал специально для Хабра руководитель группы разработки интерфейсов компании «Криптонит» Василий Беляев.

Кто увидел, где ошибка и как её можно решить — пишите в комментариях! А решение этой ошибки оставили под картинкой.

Где здесь ошибка?
Где здесь ошибка?

Если запустим этот код, то получим ошибку

Uncaught TypeError: this.clearHistory is not a function

Проблема находится на строчках 11-13 (на картинке)

this.timeout = setTimeout (function () {
        this.clearHistory();
    }, 0);

Когда мы вызываем setTimeout, то вызываем метод объекта window, и меняем область видимости с нашего конструктора на window ( window.setTimeout() ).

Именно по этой причине у нас метод clearHistory пытается вызываться у объекта window ( window.clearHistory() )

Как можно решить эту проблему?

Вариант 1

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    this.timeout = setTimeout (() => {
        this.clearHistory();
    }, 0);
};
const mуItem = new MyItem();
mуItem.refresh();

Заменить анонимную функцию на стрелочную функцию. У них отсутствует свой контекст, и они работают в контексте области видимости, включающий их самих.

Вариант 2

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    this.timeout = setTimeout (
        this.clearHistory.bind(this), 0
    );
};
const mуItem = new MyItem();
mуItem.refresh();

Явно передать контекст через метод .bind()

Вариант 3

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    const self = this;
    this.timeout = setTimeout (() => {
        self.clearHistory();
    }, 0);
};
const mуItem = new MyItem();
mуItem.refresh();

Выносим контекст в отдельную переменную и работаем с ней. Этот вариант подойдет для поддержки старых браузеров.

А как бы вы решили эту ошибку?

Теги:
Всего голосов 6: ↑3 и ↓3+2
Комментарии5

Публикации

Информация

Сайт
kryptonite.ru
Дата регистрации
Дата основания
Численность
501–1 000 человек
Местоположение
Россия