5

this.remove() is not a function. How come?

var vehicle = function () {
    return {
        init: function () {
            jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
                e.preventDefault();
                this.remove();
            });
        },
        remove: function () {
            alert('test');
        }
    }
}();

jQuery().ready(vehicle.init);

Sorry for the confusion. I'm trying to call my own "remove" function. This is simply a class to manage vehicles on my page. This is the beginning of it and it will have a lot more functions than just init/remove.

Ben
  • 60,438
  • 111
  • 314
  • 488
  • 2
    Do you want to call jQuery's remove method to remove a DOM element or your custom event that alerts 'test'? – Harmen Sep 20 '10 at 18:33

6 Answers6

5

this is a DOM element. To use jQuery's .remove() method, you need to wrap it in a jQuery object.

$(this).remove();

EDIT: If you were hoping to call the remove() function in the vehicle object, then call:

vehicle.remove();

Also, if you were hoping to shorten your .ready() call, you can do this:

jQuery(vehicle.init);

From the jQuery 1.4 release notes:

The jQuery().ready() technique still works in 1.4 but it has been deprecated. Please use either jQuery(document).ready() or jQuery(function(){}).

user113716
  • 318,772
  • 63
  • 451
  • 440
  • Umm I don't think that's the problem - he wants to call that "remove" function in the object literal there. – Pointy Sep 20 '10 at 18:33
  • I'm trying to call my own remove function – Ben Sep 20 '10 at 18:56
  • 1
    @Webnet - You can just call `vehicle.remove` if you want, or you can use @Pointy's answer to retain the value of `this` in your `init` function, but no matter what, inside the event handler, `this` will reference the DOM element that received the event. – user113716 Sep 20 '10 at 19:00
  • $(this).remove(); -- Saved me. Thanks for reminding that in order to use remove it needs to be wrapped inside a jquery object. – user_v Oct 21 '12 at 18:36
2

Note - we're all somewhat confused because it's not clear which "remove" function you want to call.

The problem is that you're passing in the reference to the "init" function, but when it's called the "this" variable will refer to the window object, not the value of "vehicle". Why? Because in Javascript the "this" value depends only on how a function is called. The fact that two functions are defined in the same object has absolutely nothing to do with it.

Try doing this instead:

jQuery(function() {
  vehicle.init();
});

When you call the "init" function that way — by explicitly referencing it as a property of the "vehicle" object — then Javascript will bind "this" to the value of "vehicle".

edit oh wait I just noticed that you're also going to have to revise your "init" function, because that code inside the "click" handler is going to be called by jQuery in such a way as to bind "this" in that context to the affected element. Thus if you want to keep the "vehicle" reference around, you'd do this:

    init: function () {
        var originalThis = this;
        jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
            e.preventDefault();
            originalThis.remove();
        });
    },
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Pointy - I don't think that's right. `vehicle` is a self executing function that returns an object which has a property `init` which is a function, so `jQuery().ready(vehicle.init);` is passing a reference to the `init` function to be use in `ready()`. – user113716 Sep 20 '10 at 18:38
  • 1
    Yes I see that, @patrick, but I think (guessing of course) that what he wants is to call that "remove" function in that same object, not the jQuery "remove". – Pointy Sep 20 '10 at 18:40
  • 1
    `this` is bound to the element, not the window, because it's used within a function that is used for an event listener. He would have to do a combination of this and I.devries solution for it to work. – Cristian Sanchez Sep 20 '10 at 18:41
  • @patrick - try it. `vehicle` is _the value returned_ by the immediate invocation of an anonymous function. – Matt Ball Sep 20 '10 at 18:42
  • @Bears - Perhaps I'm misunderstanding you, but the value returned from the immediate invocation is an object literal that is referenced by `vehicle`. I wasn't saying that @Pointy's way of calling `init` was incorrect. I'm just saying that OP's is not incorrect either. – user113716 Sep 20 '10 at 18:46
  • @patrick - to (hopefully) clarify: yes, you're right that the `init` function is actually being passed to `ready()`. However, that means that, when the `ready` callback executes, `this` (inside of `init`) won't point to `vehicle` any more. – Matt Ball Sep 20 '10 at 18:51
  • @Bears - Yes, I understand that. I'm not saying that any part of @Pointy's answer is incorrect. Admittedly, I didn't read the sentence directly after the code, and the rest of the answer wasn't there when I commented. Anyway, `vehicle` is a global variable, so OP could specify `vehicle.remove` if desired. – user113716 Sep 20 '10 at 18:58
2

Maybe you're looking for something like this?

var vehicle = new function () {

  var self = this;

  this.init = function () {
    jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
      e.preventDefault();
      self.remove();
    });
  };

  this.remove = function () {
    alert('test');
  };

};

...or like this maybe? It's kind of hard to tell what you're going for...

var vehicle = new function () {

  function remove () {
    alert('test');
  }

  this.init = function () {
    jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
      e.preventDefault();
      remove.call(this);
    });
  };

};
Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • 1
    so the 'this' inside of it will refer to the object constructed by `new`. – Dagg Nabbit Sep 20 '10 at 18:44
  • Don't use `var foo = new function () {...};`. Use `var foo = function () {...};` or just `function foo() {...};` – Matt Ball Sep 20 '10 at 18:52
  • Bears: But that's not what I'm trying to do. Invoking it with `new` changes the meaning of the `this` keyword within the function. I'm doing it intentionally... – Dagg Nabbit Sep 20 '10 at 18:55
  • Bears: in other words I'm not creating a function called vehicle, I'm creating an object called vehicle... the object is the result of calling an anonymous function as a constructor (with `new`). – Dagg Nabbit Sep 20 '10 at 18:56
  • The example the OP posted doesn't instantiate `vehicle` at any point, so adding the `new` is needed to get an instance – adamJLev Sep 20 '10 at 18:56
  • @Infinity - not true. In the OP's example, `vehicle` is the value returned by the immediate invocation of an anonymous function. – Matt Ball Sep 20 '10 at 19:02
  • @Bears - Doing `var foo = new function () {...` creates a Singleton object. As such, the value of `this` will be the object and `this.remove` (or `self.remove` using the variable) will reference the local `remove()` function. http://jsfiddle.net/K4Rym/ – user113716 Sep 20 '10 at 19:08
0
var vehicle = function () {
    return {
        init: function () {
            var self = this;
            jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
                e.preventDefault();
                self.remove();
            });
        },
        remove: function () {
            alert('test');
        }
    }
}();

jQuery().ready(function() {
   vehicle.init();
});
I.devries
  • 8,747
  • 1
  • 27
  • 29
  • 1
    No, @Harmen, "self" won't point to the "init" function, it'll point to the "this" value bound when that function is called. The problem here is that the "ready" setup is still wrong. – Pointy Sep 20 '10 at 18:39
  • "this" indeed pointed to window when not wrapped in a function, edited – I.devries Sep 20 '10 at 18:54
  • In your original answer, `this` was actually pointing to `HTMLDocument`, not `window`. – user113716 Sep 20 '10 at 19:32
0

Since you said you're trying to call your own remove function, here's how to do it:

var vehicle = (function () {
    return {
        init: function () {
            var that = this; // step one
            jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
                e.preventDefault();
                that.remove();
            });
        },
        remove: function () {
            alert('test');
        }
    }
}()); // step zero - wrap the immediate invocation in parens

jQuery(function () {
    vehicle.init(); // step two
);
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Is this any different from @Pointy's answer? Also, why wrap the function in `()`? If you're just assigning the return value to a variable, it will work either way. – user113716 Sep 20 '10 at 19:24
0

When invoking a function as a method "this" refers to the object that is invoking it. In jQuery the function passed is invoked as a method of the html element so "this" becomes the element.

To make sure you are refering to the correct object you'll need to create a reference to the original object.

   var vehicle = function () {
       var that =  {
        init: function () {
            jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
                e.preventDefault();
                that.remove();
            });
        },
        remove: function () {
            alert('test');
        }
    }
    return that;
   }();

jQuery().ready(vehicle.init);
Kenneth J
  • 4,846
  • 11
  • 39
  • 56