admin管理员组

文章数量:1245869

I have an object. It initializes a button to alert "Hello!" when it is clicked. Why won't this work?

jsfiddle: /

HTML

<button>Test</button>

JS

var MyObject = {
  testValue: "Hello!",

  testFunction: function() {
    alert(this.testValue);
  },

  init: function(button) {
    button.click(this.testFunction());
  }
}

$(document).ready(function(){
  var buttonInstance = new MyObject();
  var button = $('button');
  buttonInstance.init(button);
});

I have an object. It initializes a button to alert "Hello!" when it is clicked. Why won't this work?

jsfiddle: http://jsfiddle/kUT52/1/

HTML

<button>Test</button>

JS

var MyObject = {
  testValue: "Hello!",

  testFunction: function() {
    alert(this.testValue);
  },

  init: function(button) {
    button.click(this.testFunction());
  }
}

$(document).ready(function(){
  var buttonInstance = new MyObject();
  var button = $('button');
  buttonInstance.init(button);
});
Share Improve this question edited Jul 25, 2020 at 11:39 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Jun 28, 2013 at 20:16 Don PDon P 63.7k121 gold badges318 silver badges447 bronze badges 2
  • 3 Your code makes no sense! You can't initialize a new object literal like that. If you want to use new and treat it like a "constructor", you have to make MyObject a function. Otherwise, MyObject is an object literal and you can access it statically - MyObject.testValue – Ian Commented Jun 28, 2013 at 20:24
  • Mind blown @Ian. That makes js objects make so much more sense, thank you. – Don P Commented Jun 28, 2013 at 20:37
Add a ment  | 

3 Answers 3

Reset to default 12

Whenever you put () behind a function reference, you are executing the function. You have to pass the function reference to .click, not what the function returns (unless the function returns a function that you want to use as event handler).

Example:

button.click(this.testFunction);

But now you have another problem: Inside the function, this will refer to the DOM element and not to the object, so accessing this.testValue will return undefined.

You can use jQuery's $.proxy function to fix this:

button.click($.proxy(this.testFunction, this));

Now this will refer to the object, and you can get a reference to the clicked element via event.target.

For two reasons:

  • You are using testFunction() instead of testFunction when you bind the event, so you will be calling the function and binding the (undefined) return value.

  • When you use a method as a function, it's no longer attached to the object, so the context will not be the object when the callback is called, but the global window object.

Use the proxy method to make a function that calls the method with the right context:

button.click($.proxy(this.testFunction, this));

That's an object literal, and you'd normally use it like so :

var MyObject = {
    testValue: "Hello!",

    testFunction: function() {
        alert(MyObject.testValue);
    },

    init: function(button) {
        button.on('click', this.testFunction);
    }
}

var button = $('button');
MyObject.init(button);

FIDDLE

or passing the object:

var MyObject = {
    testValue: "Hello!",

    testFunction: function(e) {
        alert(e.data.obj.testValue);
    },

    init: function(button) {
        button.on('click', {obj: this}, this.testFunction);
    }
}

var button = $('button');
MyObject.init(button);

FIDDLE

本文标签: javascriptjQuery use an object39s method as an event handlerStack Overflow