我应该在局部变量中引用'this'吗?

时间:2012-03-07 13:49:38

标签: javascript performance this

我经常在代码中看到这一点:var me = this;。这是为什么?如果我参考这个'是否有一些性能提升?在局部变量?

8 个答案:

答案 0 :(得分:9)

如果 in 函数中的函数很有用,那么这些嵌套函数中的代码需要从外部上下文中访问this的值。

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

因为this是为每个函数调用重新建立的,所以如果没有在变量中隐藏外部this,就无法从内部函数中引用它。

答案 1 :(得分:4)

这用于保存对this的引用。稍后在代码中有一个带回调的AJAX调用(例如)。因此,回调内部this与外部不同。这就是为什么人们将“外部”this备份到变量。

我个人喜欢使用这种形式:

var that = this;

看起来很有趣:)

顺便说一句,CoffeeScript,这是一种“正确的javascript”,也有解决方法。

它有两种形式的功能定义,细箭头和胖箭头。细箭头的行为与javascript完全相同,胖箭头会自动将this绑定到外部上下文中的值。

所以,这个coffeescript

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

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

转换为此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);
  });
};

很酷,不是吗?

答案 2 :(得分:1)

this发生更改时,您仍然需要在代码中指向this

答案 3 :(得分:1)

IMO它不寻常你自己看到它 - 当有关闭时,它几乎总是被用来避免JS对{{1}的处理} value,在执行期间评估,而不是声明。

答案 4 :(得分:1)

这通常用于回调方法,其中回调运行时范围会有所不同。

示例:

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

答案 5 :(得分:1)

通常的原因是代码包含一个稍后会被调用的闭包,并且作者希望确保闭包可以访问当前的this。例如:

这是人们经常写错的代码,如下所示:

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

这是var me = this;适用于它:

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

这是因为在JavaScript中,this完全由如何调用函数定义,而不是定义函数的位置。

更多阅读(披露:两者都是我博客的链接)

答案 6 :(得分:0)

这是关闭范围。看看这两个jQuery插件的区别:

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

问题在于setInterval。当调用setInterval中的函数时,它会启动一个新的执行链,并且该链中的this绑定到window。在闭包示例中,我们在jQueryMonad(或代码中的me)中保留对我们应用插件的jQuery对象的引用。这样,我们就可以在javascript中保持我们的范围正确。

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

在第二个示例中,jQuery.proxy为您处理。

这是为了解决javascript在执行时绑定this而不是创建时间的问题。

答案 7 :(得分:0)

它与内部函数一起使用。如您所知,您可以在对象构造函数中使用函数,函数内部可以有函数。如果你看到下面的代码。

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());

当你调用getArea()时,你将根据半径10获得区域。虽然你在内部函数changeRadius中调用changeRadius(),但是这开始指向全局对象而不是你创建的对象。你可以使用var self=this construct来解决这个问题。

所以为了解决这种情况,我们可以进行以下更改。

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());