Reputation: 32923
I have following code of javascript
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
$('.click').on('click', this.show);
},
show: function () {
console.log(this.over);
}
}
Obj.init();
When this does is when user clicks a .click
link then it triggers show
function and logs out the dom element created in init
function. But the problem is then it logs out undefined. Why? How to solve it?
Upvotes: 3
Views: 1314
Reputation: 1174
Because jQuery injects the DOM element that was clicked on into 'this' as opposed to the 'Obj' object. One solution is closure:
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
$('.click').on('click', this.show());
},
show: function () {
var self = this;
return function () {
console.log("over:", self.over);
}
}
}
Obj.init();
Upvotes: 1
Reputation: 195
When binding a function to an event with jquery, the context in which this function is called is the dom object that has been clicked.
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
var that = this;
$('.click').on('click', function(){
// console.log( this ) will log the dom object
that.show.call( that )
} );
},
show: function () {
console.log(this.over);
}
}
Obj.init();
Upvotes: 0
Reputation: 944170
You pass the function stored in this.show
to on
. When it gets called, it is not called in the context of Obj
so this
is not Obj
.
You need to create a new function which isn't dependent on being called in the context of Obj
.
The easiest way to do this is with bind
:
$('.click').on('click', this.show.bind(this));
But this has limited browser support.
You can also use a closure:
var myObj = this;
var show = function () {
myObj.show()
}
$('.click').on('click', show);
Upvotes: 0
Reputation: 2121
The problem here is the scope of that this
(Obj
).
Use the following code to solve your problem.
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
$('.click').on('click', $.proxy(this.show, this));
},
show: function () {
console.log(this.over);
}
};
Obj.init();
learn more about jQuery.proxy
Upvotes: 2
Reputation: 266
try this :
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
$('.click').on('click', this.show);
},
show: function () {
// here the 'this' is the button , not the obj object ..
console.log($('.over'));
}
}
Obj.init();
another option :
var Obj = {
init: function () {
this.over = $('<div />').addClass('over');
$('body').append(this.over);
var that = this;
$('.click').on('click', function(e){
that.show.call(that, e); // calling the show function with call, causing 'this' to be obj
});
},
// 'this' is the obj
show: function (e) {
console.log(this.over);
}
}
Obj.init();
Upvotes: 4