首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >jQuery和“这个”管理?如何避免变量冲突?

jQuery和“这个”管理?如何避免变量冲突?
EN

Stack Overflow用户
提问于 2013-02-15 05:26:42
回答 5查看 990关注 0票数 16

当您编写复杂的jQuery/javascript时,如何在不重新定义先前定义的this变量的情况下使用this进行管理?在命名this变量时(随着嵌套的加深),您是否有经验法则或个人偏好?

有时我希望来自更高作用域的变量可用于嵌套函数/回调,但有时我希望有一个干净的历史/作用域;有没有一种调用函数/回调而不必担心变量冲突的好方法?如果有,你使用的是什么技术?

一些非常愚蠢的测试代码:

代码语言:javascript
复制
$(document).ready(function() {

    console.warn('start');

    var $this = $(this),

    $dog = $('#dog'),

    billy = function() {

        console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog);

        var $this = $(this);

        console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog);

    };

             // (#1)
    billy(); // BILLY! THIS: undefined | DOG: jQuery(p#dog)
             // BILLY! THIS: jQuery(Window /demos/this/) | DOG: jQuery(p#dog)

    console.log('THIS:', $this, ' | ', 'DOG:', $dog); // THIS: jQuery(Document /demos/this/) | DOG: jQuery(p#dog)

             // (#2)
    billy(); // BILLY! THIS: undefined | DOG: jQuery(p#dog)
             // BILLY! THIS:  jQuery(Window /demos/this/) | DOG: jQuery(p#dog)

    $('#foo').slideUp(function() {

                                                          // (#3)
        console.log('THIS:', $this, ' | ', 'DOG:', $dog); // BILLY! THIS: undefined | DOG: jQuery(p#dog)

        var $this = $(this); // (#10)

                                                          // (#4)
        console.log('THIS:', $this, ' | ', 'DOG:', $dog); // BILLY! THIS: jQuery(Window /demos/this/) | DOG: jQuery(p#dog)

    });

    $('#clickme').click(function() {

                                                          // (#5)
        console.log('THIS:', $this, ' | ', 'DOG:', $dog); // THIS: undefined | DOG: jQuery(p#dog)

        var $this = $(this);

                                                          // (#6)
        console.log('THIS:', $this, ' | ', 'DOG:', $dog); // THIS: jQuery(button#clickme) | DOG: jQuery(p#dog)

        $('#what').animate({
            opacity : 0.25,
            left    : '+=50',
            height  : 'toggle'
        }, 500, function() {

                                                              // (#7)
            console.log('THIS:', $this, ' | ', 'DOG:', $dog); // THIS: undefined | DOG: jQuery(p#dog)

            var $this = $(this);

                                                              // (#8)
            console.log('THIS:', $this, ' | ', 'DOG:', $dog); // THIS: jQuery(div#what) | DOG: jQuery(p#dog)

        });

    });

             // (#9)
    billy(); // THIS: undefined | DOG: jQuery(p#dog)
             // THIS: jQuery(div#foo) | DOG: jQuery(p#dog)

    console.warn('finish');

});

A full demo page can be found here (jsbin.com)

注意:正如您所看到的,为了便于参考,我已经用数字(#XX)“标记”了注释。

观察1:

标记(#1)

代码语言:javascript
复制
BILLY! THIS: undefined | DOG: jQuery(p#dog)

反问句:为什么$this是未定义的,而$dog是可访问的?

回答:,因为该作用域中的var正在重新定义$this;只是在该作用域中定义$this之前,我正在尝试记录它。

如果我注释掉var $this = $(this);,那么标记(#1)将返回:

代码语言:javascript
复制
BILLY! THIS: jQuery(Document index2.html) | DOG: jQuery(p#dog)
BILLY! THIS: jQuery(Document index2.html) | DOG: jQuery(p#dog)

同样的逻辑适用于标记(#2)、(#3)、(#4)、(#5)、(#6)、(#7)和(#8)

基于这个观察(如果我错了请纠正我),我假设我可以把var $this = $(this);放在函数的底部,并且当前作用域应该知道我想要使用当前作用域的$this (即使它还没有定义),而不是父作用域的$this (即使它的定义的)。

避免$this冲突的可能解决方案:

如果想要在其他闭包/函数/回调外部/内部缓存$(this)并避免冲突,那么应该使用不同的变量标签,例如:

代码语言:javascript
复制
var $$ = $(this);
var $this2 = $(this);
var $t = $(this);
var $that = $(this);

问题:

上面的解决方案是如何避免$this冲突的吗?如果没有,你最喜欢的技术是什么?

观察2:

标记(#9)

代码语言:javascript
复制
THIS: undefined | DOG: jQuery(p#dog)

...由于上述原因,$this未定义,但是:

代码语言:javascript
复制
THIS: jQuery(div#foo) | DOG: jQuery(p#dog)

... $this现在是$('#foo')

问题(S):

到底为什么会发生这种情况?

是因为$this是通过标记(#10)重新定义的吗

(嗯,我觉得我需要用谷歌搜索“javascript中的垃圾收集”。)

同样,在编写复杂的jquery/javascript时,避免这种类型的变量冲突的最佳方法是什么?

我希望这些不是可怕的问题。提前感谢您抽出时间来帮助我。:)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-02-15 05:37:47

在内部作用域中重新声明var $this时看到的行为称为hoisting。这就是为什么对于该作用域中所需的任何变量,在每个作用域的开头都应该始终只有一条var语句的原因之一--这并不是说这是必要的,只是因为它做了相同的事情,并且变量名更容易定位。

至于必须在深度嵌套的作用域中使用变量..这可能是有问题的迹象(太多嵌套,单一责任,等等)。如果您需要大量使用某些构造,请考虑将它们添加到对象的作用域中,而不是为它们指定以2结尾的名称。至少应该给它们起描述性的名称(我通常只在一个作用域中使用$this = $(this),这是为了避免重复调用$() )。self通常用于引用其自身作用域内的函数定义中的当前对象。

代码语言:javascript
复制
var Dog = function (boy, dog) {
    this.boy = boy;
    this.dog = dog;
    this.$clickme = $("#clickme");
}

Dog.prototype.bind = function () {
    var self = this;

    self.$clickme.on('click', function() {
        var $this = $(this);
        console.log('THIS:', $this, ' | ', 'DOG:', self.dog);

        $('#what').animate({
            opacity : 0.25,
            left    : '+=50',
            height  : 'toggle'
        }, 500, function() {
            var $this = $(this);
            console.log('CLICKME:', self.$clickme, ' | ', 'DOG:', self.dog);
        });
    });
}
票数 3
EN

Stack Overflow用户

发布于 2013-02-15 05:34:37

你实际上遇到了变量提升的问题:

代码语言:javascript
复制
billy = function() {

    console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog);

    var $this = $(this);

    console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog);

};

在运行时实际上是这样解释的:

代码语言:javascript
复制
billy = function() {

    var $this;

    console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog); // $this hasn't been set to anything yet...

    $this = $(this);

    console.log('BILLY!', 'THIS:', $this, ' | ', 'DOG:', $dog);

};

JavaScript将变量和函数声明提升到作用域块的顶部,以便您可以在手动声明它们之前引用它们。当人们从作用域块之外引用相同名称的变量时,这会给他们带来麻烦,正如您在示例中清楚地看到的那样。

票数 8
EN

Stack Overflow用户

发布于 2013-02-15 05:30:39

您已经体验到了scope和JavaScript带来的乐趣。很多人喜欢做的一件事是,如果您需要访问回调中的当前作用域,请将其定义为self,如下所示:

代码语言:javascript
复制
var $ = require('jquery')
  , database = require('database')

$.on('click', function(action) {
  var self = this;
  database.connect(function() {
    database.putSync(self.action.button);
  });
});

请注意,当调用'connect‘时,"this“的作用域被重置为回调的作用域,而不是点击处理程序的作用域,这就是您将作用域存储在可访问变量中的原因。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14884342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档