Понимание `this` в обработчиках событий jquery - PullRequest
0 голосов
/ 17 июня 2020

Javascript newb ie здесь. Я пытаюсь понять this и bind в контексте jquery обработчиков событий . Я просматриваю фрагмент кода из задачи MVC код здесь , и у меня есть вопрос.

Давайте посмотрим на строку 56:

$('#new-todo').on('keyup', this.create.bind(this));

Отрывок кода для контекста:

var App = {
        init: function () {
            this.todos = util.store('todos-jquery');
            this.todoTemplate = Handlebars.compile($('#todo-template').html());
            this.footerTemplate = Handlebars.compile($('#footer-template').html());
            this.bindEvents();

        bindEvents: function () {
            $('#new-todo').on('keyup', this.create.bind(this));
            $('#toggle-all').on('change', this.toggleAll.bind(this));
            $('#footer').on('click', '#clear-completed', this.destroyCompleted.bind(this));
            $('#todo-list')
                .on('change', '.toggle', this.toggle.bind(this))
                .on('dblclick', 'label', this.edit.bind(this))
                .on('keyup', '.edit', this.editKeyup.bind(this))
                .on('focusout', '.edit', this.update.bind(this))
                .on('click', '.destroy', this.destroy.bind(this));
        },

    create: function (e) {
        var $input = $(e.target);
        var val = $input.val().trim();

        if (e.which !== ENTER_KEY || !val) {
            return;
        }

        this.todos.push({
            id: util.uuid(),
            title: val,
            completed: false
        });

        $input.val('');

        this.render();
    },

Мой вопрос

Я понимаю, что при использовании jquery, this по умолчанию относится к «элементу, для которого мы вызвали метод» (в данном случае #new-todo), поэтому в этом коде мы хотим явно привязать this к объекту App.

В этом примере оба символа this следуют «слева от правила точки» и относятся к App. Пока все хорошо.

Chrome debugger screenshot of this pointing to app in line 56

Chrome debugger screenshot of this pointing to app in line 57

Исходя из этого поведения, я ожидаю, что this, если не внутри , функция обратного вызова должна ссылаться на родительский app, (и this внутри функция обратного вызова должна по умолчанию использовать элемент с идентификатором #new-todo, если привязан к какому-то другому значению).

Следовательно, если я вызываю this.create, не привязывая его ни к чему, this все равно должен ссылаться на App, верно? НЕПРАВИЛЬНО.

Chrome debugger screenshot of this pointing to #new-todo in line 56

Chrome debugger screenshot of this pointing to #new-todo in line 57

Как видите, первое this теперь относится элементу с ID #new-todo. (И this в других слушателях событий ниже также относится к jquery обернутому объекту!)

Может кто-нибудь помочь мне понять, почему?

1 Ответ

0 голосов
/ 21 июня 2020

Я обнаружил проблему (с моим вопросом), поэтому я решил опубликовать решение на случай, если оно кому-то поможет в будущем.

Я понял, что мое первоначальное понимание this и bind() было правильно, поэтому я, должно быть, ошибаюсь в другом.

Оказывается, (1) я сделал неверное предположение о том, как работает отладчик (2) Мне нужно было проверить, когда выполнялась каждая часть кода

(1) Отладчик

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

(2) Время выполнения кода

Когда выполнение кода приостановлено для моей точки останова, я уже был внутри метода create, поэтому this в this.create и .bind(this) отражали значение this в рамках метода create.

введите описание изображения здесь

...