Om3ga
Om3ga

Reputation: 32923

can't access variable in another function inside object literal

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

Answers (5)

Spencer Lockhart
Spencer Lockhart

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

ganmor
ganmor

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

Quentin
Quentin

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

Sandeep
Sandeep

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

IdanHen
IdanHen

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

Related Questions