Using _self so I always can have object context

196 views Asked by At

What is the proper way to use _self to always have access to an object? Is using _self ok, or is it bad practice?

I want a good way to get at myObject's attributes and methods, even from functions that aren't called in myObject's context. There are solutions like .bind(this), using _self, and jQuery's $.proxy().

For example:

var myObject = {
  name: 'Tyrion',
  alias: 'imp',
  _self: function() {
    return this;
  },

  // I know this context is fine, but let's pretend it's being called from elsewhere.
  getAlias: function() {
    var _self = myObject._self();
    return _self.alias;
  } 
}
3

There are 3 answers

1
Mke Spa Guy On

is determined by the invocation of the function. (aka, the way the function is called) See my other answers for more details.

var myObject = {
    name: 'Tyrion',
    alias: 'imp',
    _self: function () {
        return this;
    },

    // I know this context is fine, but let's pretend it's being called from elsewhere.
    getAlias: function () {
        var _self = myObject._self();
        return _self.alias;
    }
};

//member invocation
console.log(myObject._self() === myObject); // true

var aFucntion = myObject._self;
//functional invocation
console.log(aFucntion() === myObject); // false
console.log(aFucntion() === this); //true

Instead of worrying about the context of , a workaround is to assign to a value in an outer function, and then access that value in an inner functions. This is called closure

var MyObject = function (title) {
    var _self = this,
        helper = function () {
            return _self.title + " " + _self.name;
        };
    this.title = title;
    this.fullName = function () {
        return helper(); //functional invocation
        //if helper used this, this would be global
    };
    this.name = 'Tyrion';
    this.alias = 'imp';
    this.getAlias = function () {
        //access to _self through closure
        return _self.alias;
    };
};

//constructor invocation
var aObject = new MyObject("Mr.");
console.log(aObject.getAlias()); //imp
console.log(aObject.fullName()); //Mr. Tyrion

FYI:

If _self returns myObject, context would not mater.

_self: function () {
        return myObject;
    }
0
kalley On

In order to do what you're looking to do, you'd have to change a few things. @elclanrs is right about what your this context is. I'll put two options below.

var myObject = {
  name: 'Tyrion',
  alias: 'imp',
  // I know this context is fine, but let's pretend it's being called from elsewhere.
  getAlias: function() {
    // you'd have to do this in every method.
    var _self = this;
    return _self.alias;
  } 
}

The other option is a bit different, and not as usable, but I'm adding it so you can see it:

var myObject = function() {
    var _self = this;
    _self.name = 'Tyrion';
    _self.alias = 'imp';
    _self.getAlias = function() {
        return _self.alias;
    };
};

in the second instance, getAlias would be better as a prototype method, but you won't have access to the _self variable, only this.

0
jaredwilli On

You can do this too but I wouldn't necessarily recommend it.

var obj = {
  _self: this.obj, // if you don't have .obj it points to window
  thing: 'thingy',
  alsoThis: function() {
    return 'another thing'
  }
};

obj._self;

It's also possible that since it's not within a closure, or a function in otherwords, the context of this._self may be incorrect if the context is changed by the scope which its referenced in.

Generally, I just do var _self = this; right before a function which I am nesting another function within that requires the this context outside the parent function since the nested one will not have the ability to access the value of this being nested.

That's usually not too common in my experience, and you really shouldn't be declaring such a property/var that needs to be used for the purpose that _self vars serve. It isn't a good practice and would be best to not do.

What if you run into a situation where you need to have _self = some other context?