Should I reference 'this' in local variabl

2019-06-28 01:14发布

问题:

I often see this in code: var me = this;. Why is that? Is there some performance gain if I reference 'this' in local variable?

回答1:

It's useful if there are functions inside a function, such that code in those nested functions needs access to the value of this from the outer context.

function example() {
  var me = this;
  document.getElementById('whatever').onclick = function() {
    me.clicked = 1;
  };
}

Because this is established anew for every function call, without stashing the outer this in a variable there'd be no way to reference it at all from the inner function.



回答2:

This is used to save reference to this. Later in the code there's an AJAX call with a callback (for example). So, inside of that callback this is not the same as outside. That's why people back up "outer" this to a variable.

I personally like to use this form:

var that = this;

Looks funny :)

By the way, CoffeeScript, which is a kind of "javascript done right", has a fix for this as well.

It has two forms for function definition, thin arrow and fat arrow. Thin arrow behaves exactly like in javascript, and fat arrow automatically binds this to a value from outer context.

So, this coffeescript

Account = (customer, cart) -> # thin arrow
  @customer = customer
  @cart = cart

  $('.shopping_cart').bind 'click', (event) => # fat arrow
    @customer.purchase @cart

gets transformed to this javascript

var Account;
Account = function(customer, cart) {
  var _this = this;
  this.customer = customer;
  this.cart = cart;
  return $('.shopping_cart').bind('click', function(event) {
    return _this.customer.purchase(_this.cart);
  });
};

Cool, isn't it?



回答3:

It is so that when this changes, you still have a reference to this at the point in the code you need.



回答4:

IMO it's unusual you'd see that on its own--it's a construct almost always used when there are closures involved to avoid JS's treatment of the this value, evaluated during execution, not declaration.



回答5:

That is often used for callback methods, where the scope would be different when the callback runs.

Example:

var me = this;
$.getJSON(url, function(data) {
  // here "this" will be "window", so "me" is used to access the object
})


回答6:

The usual reason is that the code contains a closure that will get called at some later time, and the author wants to make sure the closure has access to the current this. Example:

Here's code that people frequently write incorrectly, like this:

var obj = {
    name: "Fred",
    foo: function() {
        setTimeout(function() {
            alert(this.name); // <=== Fails, `this` is no longer `obj`
        }, 1000);
    }
};
obj.foo();

Here's that var me = this; applied to it:

var obj = {
    name: "Fred",
    foo: function() {
        var me = this;
        setTimeout(function() {
            alert(me.name); // <=== Works now
        }, 1000);
    }
};
obj.foo();

This comes about because in JavaScript, this is defined entirely by how a function is called, not where the function is defined.

More reading (disclosure: both are links to my blog):

  • You must remember this
  • Closures are not complicated


回答7:

That is for closure scope. Look at the difference in these two jQuery plugins:

$.fn.blinkClosure = function() {
    var jQueryMonad = this, toggleClass = this.toggleClass;
    setInterval(function() {
        toggleClass.apply(jQueryMonad, ['invisible']);
    }, 500);
};

The problem is with setInterval. When the function in setInterval gets called, it starts a new chain of execution, and this in that chain is bound to window. In the closure example, we keep a reference to the jQuery object we apply the plugin to in the jQueryMonad (or me in your code). This way, we can keep our scope correct in javascript.

$.fn.blink = function() {
    setInterval($.proxy(function() {
        this.toggleClass('invisible');
    }, this), 500);
};

In the second example, jQuery.proxy handles that for you.

This is to solve the issues when javascript binds this at execution time, instead of creation time.



回答8:

It is used with inner functions. As you know, you can have functions in object constructors and there can be functions inside functions. If you see the code below.

function Circle(radius){
this.radius=radius;
this.getArea=function(){
                    var changeRadius=function(){
                            this.radius=20; //here this points to global
                        }
                    changeRadius();
                    return Math.PI*Math.pow(this.radius, 2);
                    }
}

var cd= new Circle(10);
console.log(cd.getArea());

When you call getArea(), you will get area according to radius 10. Although you are calling changeRadius() but inside inner function changeRadius, this starts to point to global object instead of the object you created. You use var self=this construct to get around here.

so in order to get around this situation we can have the following changes.

function Circle(radius){
var self=this;
this.radius=radius;
this.getArea=function(){
                    var changeRadius=function(){
                            self.radius=20;
                        }
                    changeRadius();
                    return Math.PI*Math.pow(this.radius, 2);
                    }
}

var cd= new Circle(10);
console.log(cd.getArea());