admin管理员组

文章数量:1418113

OK, this may sound ultra-simple, but since it's the very first time I'm getting really serious with JavaScript/jQuery, I want to know what's the best way to go about it.

So, here's the situation:

var someClass = function()
{
    var someProperty;

    /*********************************
     Initialisation
     *********************************/

    this.construct = function(options){

        this.someProperty = "someValue";

        $("#someDiv").click(function(){
            // I want to access "this" (= the someClass object) here
        });

    }
}

var theObj = new someClass();

Now, here's what: Given that, in my particular case, theObj is just a single (global) object, I could obviously do :

$("#someDiv").click(function(){
     console.log(theObj.someProperty);
});

But I most definitely do not like it - and there must be a more elegant/object-oriented-friendly way.


So, how would you go about it?

OK, this may sound ultra-simple, but since it's the very first time I'm getting really serious with JavaScript/jQuery, I want to know what's the best way to go about it.

So, here's the situation:

var someClass = function()
{
    var someProperty;

    /*********************************
     Initialisation
     *********************************/

    this.construct = function(options){

        this.someProperty = "someValue";

        $("#someDiv").click(function(){
            // I want to access "this" (= the someClass object) here
        });

    }
}

var theObj = new someClass();

Now, here's what: Given that, in my particular case, theObj is just a single (global) object, I could obviously do :

$("#someDiv").click(function(){
     console.log(theObj.someProperty);
});

But I most definitely do not like it - and there must be a more elegant/object-oriented-friendly way.


So, how would you go about it?

Share Improve this question asked Sep 15, 2014 at 7:13 Dr.KameleonDr.Kameleon 22.8k21 gold badges124 silver badges237 bronze badges 1
  • 4 A tip: Functions can acces the variables in all outer scopes. – Teemu Commented Sep 15, 2014 at 7:15
Add a ment  | 

4 Answers 4

Reset to default 3

Since you're not using the .prototype to add methods, and are instead creating them as privileged methods within the class, just use an additional variable in the constructor's scope that refers to the object:

var someClass = function() {

    var self = this;

    ...

};

This allows you to preserve the normal jQuery semantics that this refers to the clicked element, whilst making self available to refer to the wrapping object. For this semantic preservation reason I would specifically remend against using .bind(this).

Regarding your final proposed "solution" of just using theObj inside the callback - you should also never refer to an object by its own name from inside itself, since those names are not under your control and may change. It might be safe in your current code, but it's a nightmare for code maintenance and code isolation.

There're many approaches. Yours is one and it's one of most simpler and effective approaches, and as far as I know, it implies less performance penalties (it uses closures).

Other approaches:

.bind(this).

bind changes the meaning of this inside the scope of a given function. If you do the following, click handler this keyword will be the outter this reference:

 // This will bind outter "this" as the object referenced by 
 // inner this
 $("#someDiv").click(function(){
      console.log(this.someProperty);
 }.bind(this));

.call(this, arg1, argN).

call defines the reference of this within the called function. The first parameter is the this reference to be this in the called function scope. Next parameters are callable function arguments (if the function has them). This isn't for the click handler use case.

There're some edge cases where you would want to use call. For example, if you want to route an event in some custom way and the event handler receive a custom context:

 var that = this;

 $("#someDiv").click(function(){
      // Some handler function from the outter scope. It will have a "this"
      // reference to the outter "this" object reference
      someHandlerFunction.call(that, { currentElement: this, timeStamp: Date.now() });
 });

.apply(this, [arg1, argN]).

Same as call, function arguments are given in an array instead of as actual function arguments separated by a ma like a regular function call. Also, not applicable in your use case.

Conclusion

Prefered approach: yours. bind/call/apply approach is less performant and it has a big drawback if you use in DOM event handlers: you lose the standard this meaning as defined by DOM - the reference of the DOM element which originated the event -.

Use bind in other edge cases, where this would mean window JavaScript object, and you want to avoid the closure approach.

You can bind to keep the same context:

$("#someDiv").click((function(){
        // same this as externally
}).bind(this));

Or you can define a variable in the closure :

var obj = this;
$("#someDiv").click(function(){
        // your this is obj
});

Or if using Firefox (and soon other browsers) you can use an arrow function :

$("#someDiv").click(() => {
        // same this as externally
});

Use bind or save a reference to this:

$("#someDiv").click((function() {
  console.log(this.someProperty);
}).bind(this));

or

var that = this;

$("#someDiv").click((function(){
   console.log(that.someProperty);
});

本文标签: javascriptAccess quotthisquot from within anonymous functionStack Overflow