Correct way to bind "this" to JavaScript event callbacks?

I created a class called SearchBox to handle interaction with the search (delayed trigger, search by pressing the enter key, preventing the search when it is active, synchronizing the results when the search is completed and the text is changed, etc.).

All class methods are prototypes designed to be accessed through this. In the following code, suppose that it pis a prototype of a class.

p.registerListeners = function () {
    $(this.element).on('keypress', this.searchKeyPressed);
};

p.unregisterListeners = function () {
    $(this.element).off('keypress', this.searchKeyPressed);
};

This does not work, because when the keypress event calls the handler searchKeyPressed, it does not do this in context this. The only solution I can come up with is one that only supports modern browsers, which links the callback to this, which actually creates a new function. Since it creates a new function, I have to cache it in order to delete it later, since I need to pass the same link to offwhat I passed on.

Is there a better way to do this than this, or is this normal?

var boundKeyPressed;

p.registerListeners = function () {
    boundKeyPressed = this.searchKeyPressed.bind(this);
    $(this.element).on('keypress', boundKeyPressed);
};

p.unregisterListeners = function () {
    $(this.element).off('keypress', boundKeyPressed);
};

, , , jQuery.on , , this , . , on('eventname',instance.func), this "currentTarget" ( "target" ), on('eventname','selector',instance.func), this , . func , instance.

+4
5

, .

:

$(this.element).on('keypress.mynamespace', this.searchKeyPressed.bind(this));

:

$(this.element).off('.mynamespace');
+2

bind jQuery.proxy , can unbind:

jQuery.proxy , jQuery.proxy(function, context) - , :

p.registerListeners = function () {
    $(this.element).on('keypress', $.proxy(this.searchKeyPressed, this));
};

p.unregisterListeners = function () {
    $(this.element).off('keypress', $.proxy(this.searchKeyPressed, this));
};
+2

, , ( , ), , , "".

, .bind , polyfill.

-: 100% , , , , - .

addEventListener ( attachEvent), handleEvent.

, , , :

class Input {
  constructor (events) {
    this.events = events || [];
  }

  handleEvent (e) {
    var input = this;
    var method = e.type;
    if (typeof input[method] === "function") {
      input.dispatchEvent(method, e);
    }
  }

  dispatchEvent (method, content) {
    var input = this;
    input[method](content);
  }

  listen (el, events) {
    var input = this;
    events = events || input.events;
    events.forEach(event => el.addEventListener(event, input));
    return this;
  }

  ignore (el, events) {
    var input = this;
    events = events || input.events;
    events.forEach(event => el.removeEventListener(event, input));
    return this;
  }
}


class Keyboard extends Input {
  constructor () {
    super(["keydown", "keyup"]);
    var keyboard = this;
    keyboard.keys = new Set();
  }

  press (key) { this.keys.add(key); }
  release (key) { this.keys.delete(key); }
  isPressed (key) { return this.keys.has(key); }

  keydown (e) {
    var key = e.keyCode;
    this.press(key);
  }

  keyup (e) {
    var key = e.keyCode;
    this.release(key);
  }
}

:

var gameplayEvents = ["keyup", "keydown"];
var keyboard = new Keyboard();
keyboard.listen(canvas, gameplayEvents);

// ongameover
keyboard.ignore(canvas, gameplayEvents);

, 100% JS. jQuery, extJS .. , . -, mousedown; , - handleEvent, this handleEvent.

, . , .

jQuery ( ) , , .

, , , ES6...... .

, , :

function Parent (args) { }
extend(Parent.prototype, { /*public-methods*/ });

function Child (args) {
  Parent.call(this);
  // construct
}
extend(
  Child.prototype,
  Parent.prototype,
  { /*public-override-methods*/ },
  { constructor: Child }
);

, , 100%.
ES7, ( ).

, .

+1

.

p.registerListeners = function() {
    var me = this;

    $(me.element).on('keypress', function() {
        me.searchKeyPressed.apply(me, arguments);
    });
};

.

0

bind(this) - , .bind. bind , , , : $el.on("click", this.handler.bind(this)), $el.off("click", this.handler.bind(this)), . (this.handler.bind(this) !== this.handler.bind(this)) (, this.handler = this.handler.bind(this)), $el.on("click", this.handler) $el.off("click", this.handler), .

. , , , .

function MyObject($el) {
    this.testValue = "I am really this!";
    this.$el = $el;
    this.onClick = this.onClick.bind(this);
    this.render();
}
MyObject.prototype.onClick = function(evt) {
    console.log(this.testValue); // logs "I am really this!"
}
MyObject.prototype.render = function() {
    var $a = $("<a>", {"text": "Click on me!"}).appendTo($el.empty());
    $a.on("click", this.onClick);
}
0
source

Source: https://habr.com/ru/post/1618199/


All Articles