views:

82

answers:

6

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.

+2  A: 

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(){}).

patrick dw
Umm I don't think that's the problem - he wants to call that "remove" function in the object literal there.
Pointy
I'm trying to call my own remove function
Webnet
@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.
patrick dw
A: 
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
I don't think that will work.
Pointy
Surely this won't work, `self` points to the init function
Harmen
@Harmen: nope, `self` points to the `vehicle` that's about to be returned, so long as it's called like this: `vehicle.remove()`. With this call: `jQuery().ready(vehicle.init);` `self` points to `window`.
Matt Ball
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
"this" indeed pointed to window when not wrapped in a function, edited
I.devries
In your original answer, `this` was actually pointing to `HTMLDocument`, not `window`.
patrick dw
+2  A: 
Pointy
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()`.
patrick dw
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
`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.
CD Sanchez
@patrick - try it. `vehicle` is _the value returned_ by the immediate invocation of an anonymous function.
Matt Ball
@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.
patrick dw
@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
@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.
patrick dw
+2  A: 

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);
    });
  };

};
no
Why `new function`?
Harmen
so the 'this' inside of it will refer to the object constructed by `new`.
no
Don't use `var foo = new function () {...};`. Use `var foo = function () {...};` or just `function foo() {...};`
Matt Ball
#1 is the way to go.
Infinity
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...
no
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`).
no
The example the OP posted doesn't instantiate `vehicle` at any point, so adding the `new` is needed to get an instance
Infinity
@Infinity - not true. In the OP's example, `vehicle` is the value returned by the immediate invocation of an anonymous function.
Matt Ball
@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/
patrick dw
A: 

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
It works, thanks!
Webnet
It works without wrapping in () so why do that?
Webnet
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.
patrick dw
@Webnet: http://stackoverflow.com/questions/939386/
Matt Ball
A: 

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