callback with `this` confusion

前端 未结 2 1487
故里飘歌
故里飘歌 2020-12-21 16:41

I have this clock object:

var Clock = {
    start: function () {
      $(\'#btnScrollPause\').show();
      $(\'#btnScrollResume\').hide();

      advance();         


        
相关标签:
2条回答
  • 2020-12-21 16:51

    This is related to how this keyword works in JavaScript. When you pass a method as a callback to another function the method is detached from the object and the this keyword doesn't refer to object. Additionally jQuery event methods modify the this value of callbacks to refer to the owner of the event, i.e. the DOM elements.

    One option that you have is using the .bind function:

    $('#btnScrollPause').click(Clock.pause.bind(Clock));
    

    A related question: How does the “this” keyword work?

    0 讨论(0)
  • 2020-12-21 16:54

    The this object binding is volatile in JavaScript...that is, it doesn't always point to the same object and its binding can change from one line of code to the very next. How you invoke the code that contains the word this determines what object it will bind to.

    Had you made an instance of Clock (i.e. var c = new Clock()) and then said:

    $('#btnScrollPause').click(c.pause);
    

    It would have worked because this would be bound to the instance of the Clock referenced by the c variable.

    But as it stands with your code, this is bound to your button because that is the object that initiated the code.

    Here's a checklist that you can follow to know what this will bind to...

    If the code that contains this is invoked:

    1. As a method or property of an object instance (through an instance variable):

      var o = new Object(); 
      
      // "this" will be bound to the "o" object instance
      // while "someProperty" and "someMethod" code executes
      o.someProperty = someValue;
      o.someMethod();
      
    2. Via a .call(), .apply(), .bind() or Array.prototype.fn invocation:

      // "this" will be bound to the object suppled as the "thisObjectBinding"
      someFunction.call(thisObjectBinding, arg, arg);
      someFunction.apply(thisObjectBinding, [arg, arg]);
      var newFunc = someFunction.bind(thisObjectBinding, arg, arg);
      

      Additionally, several Array.prototype methods allow for a thisObject to be passed which will alter the binding for the duration of the method call:

      Array.prototype.every( callbackfn [ , thisArg ] )
      Array.prototype.some( callbackfn [ , thisArg ] )
      Array.prototype.forEach( callbackfn [ , thisArg ] )
      Array.prototype.map( callbackfn [ , thisArg ] )
      Array.prototype.filter( callbackfn [ , thisArg ] )
      
    3. If none of the other scenarios apply, Default binding occurs.

      3a. With "use strict" in effect: this is undefined

      3b. Without "use strict" in effect: this binds to the Global object

    ** NOTE: this binding can also be affected by using eval(), but as a general best practice, the use of eval() should be avoided.

    0 讨论(0)
提交回复
热议问题