Привязка контекста объекта к внутренним фунциям метода

308
28 июля 2017, 03:34

У объекта есть метод, записанный в прототип:

ServisePlate.prototype.disclose = function() {
    console.log('запустилась функция disclose');
    function showBody() {
        if(this.elem.offsetHeight < (this.body.offsetHeight + this.initialSize)) {
            this.elem.style.height = this.elem.offsetHeight + this.settings.step + 'px';
            setTimeout(showBody.call(this), this.settings.speed);
        }
    }
    function hideBody() {
        if(this.elem.offsetHeight > this.initialSize) {
            this.elem.style.height = this.elem.offsetHeight - this.settings.step + 'px';
            setTimeout(hideBody.call(this), this.settings.speed);
        }else {
            this.elem.style.height = '';
        }
    }
    if(this.elem.offsetHeight == this.initialSize || this.elem.offsetHeight >= (this.body.offsetHeight + this.initialSize)) {
        if(this.elem.offsetHeight == this.initialSize) {
            console.log('Сработало условие 1');
            showBody.call(this);
        } else {
            console.log('Сработало условие 2')
            hideBody.call(this);
        }
   }
}   

У него есть две внутренние функции hideBody и showBody.
Как правильно привязать к ним контекст объекта? Через call(this), как в коде выше все функции запускаются и отрабатывают за исключением переменных объявленных в конструкторе - это объект:

this.settings = {
    step: 30,
    speed: 1000
}

его свойства задают шаг наращивания пикселей и таймаут повторного запуска. Так вот функции отрабатываю так, словно их нет..... хотя из этих функций выводятся их значения через console.log.
По идее с такими значениями каждую секунду к свойству height должно прибавляться 30px, но нужная высота получается моментально, без плавного прибавления.
Через apply все происходит точно так же, а через bind вовсе не запускаются функции.
Как быть?

Answer 1

Налицо неверное использование технологии.

Самое просто решение: перенести эти функции в прототип объекта - нет нужды менять контекст, нет проблем с неправильным использованием call.

Конкретно в данном коде проблема заключается в том, что setTimeout, первым параметром ожидает функцию. Применение же call - сразу вызывает функцию.

То есть, в данном случае надо было использовать bind

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

Например:

var showBody = ()=>{ 
    ...
    setTimeout(showBody, this.settings.speed)
}
READ ALSO
Проблема с Bootstrap 3

Проблема с Bootstrap 3

Использую bootstrapmin, при нажатии на кнопку открытия меню на мобильных разрешениях, оно открывается и тут же закрывается, не давая перейти на ссылки

442
Обработка нажатия клавиш jQuery

Обработка нажатия клавиш jQuery

У меня есть функция, которая по клику мыши выделяет элемент (добавляет класс selected)

282
Оптимизация PHP-кода: экономия на спичках

Оптимизация PHP-кода: экономия на спичках

Даст ли улучшение производительности ручной inline функций и замена include содержимым вызываемого файла?

293
Выбор СУБД для большого проекта [требует правки]

Выбор СУБД для большого проекта [требует правки]

Здравствуйте дорогие друзьяСобственно надо сделать веб (браузерную) программу для большой организации где за один только сезон т е год может...

252