2

我知道 JavaScript 会自动为每个函数/方法分配参数this,并且this绑定到包含它的对象。

方法是存储为对象属性的函数。所以在一个方法中,this可以用来修改或从包含它的对象中检索值。但是,如果该方法作为函数调用,而不是作为对象的属性调用,则this绑定到全局,而不是对象。

解决方法是分配:

var that = this;

在方法内部,以便内部函数可以this通过变量访问that

我的问题是:为什么需要这种解决方法?你不能一直使用方法吗?为什么你会调用一个非常好的方法作为内部函数,然后必须创建另一个变量,以便它具有如果它被调用为方法时所拥有的访问权限?

我必须在这里遗漏一些重要的东西,如果有一个愚蠢的问题标签,我会使用它。(有人可以做一个吗?)

4

4 回答 4

2

我希望我能正确理解你的问题。因为你说它的方式有点介意-f*** XD。

但据我了解。我将回答你的问题,如“我们用这个that技巧做什么?”。

所以这里是一个完全健康的对象。

var myobject = {
    firstMethod : function(){
        this.secoundMethod(); // calls the other method

    },
    scoundMethod : function(){
        return 'hi from method 2' ;
    }
} 

现在我想做一些 jquery 魔术(或任何其他具有回调功能的东西)。我打算使用 jQuery,但可以随意做其他事情。

var myobject = {
    firstMethod : function(){
        var _this = this ;
        this.secoundMethod(); // calls the other method

        $('.myClass').animate({'width':300} , 300 , function(){
            // this is a call back functon which will be called as soon as the animation ends
            // the problem is that if i call @var : `this` , it wont work because im in 
            // another scope other than the firstMethod .
            // so the following will throw an error .
            this.secoundMethod(); // error

            // to solve this you need the @var : `that` , or in my case i love it to be _this
            _this.scoundMethod() // this will work .


        })

    },
    scoundMethod : function(){
        return 'hi from method 2' ;
    }
} 

所以主要_this(在我的情况下)用于范围 things 。所以我可以访问其他范围内的对象范围。老实说,我在其他地方使用过这个技巧(在 99% 的情况下);

即使剩下的 1% 基本上也是相同的想法,但嵌套更深,或者有很多闭包之类的东西。

这有多危险?!

嗯,这取决于你有多聪明。这是另一个大脑示例

var myobject = {
    firstMethod : function(){
        var _this = this ,
            someObject : {

                firstMethod  : function(){
                    this.scoundMethod(); // if you log this you will get 'the wrong method'.
                    _this.scoundMethod(); // in here you get 'hi from method 2'.

                },
                scoundMethod : function(){
                    return 'the wrong method';
                }
            };

    },
    scoundMethod : function(){
        return 'hi from method 2' ;
    }
} 

如您所见,这很危险,不是因为它不起作用,而是因为它起作用的恐惧 id。因为如果你有类似命名的函数并且你有一个错过的范围,你最终会花费数小时的时间进行挖掘。如果你没有那个..你会得到一个很好的错误,你可以立即修复

这能走多久。

你可以随心所欲地筑巢吗?但有后果(很少吧?!)。享受以下内容,不要在家里尝试。

var myobject = {
    firstMethod : function(){
        var _this = this ,
            someVar = [1 , 2 , 3 ] ;

            this.scoundMethod(function(){
                var that = this;
                $.each(someVar,function(elementName){
                    var them = this;
                    $('.'+elementName).animate({} , 300 , function(){
                        console.log(them) // logs the element
                        console.log(_this.scoundMethod()) // logs 'hi from method 2'
                    })
                })
            }

    },
    scoundMethod : function(){
        return 'hi from method 2' ;
    }
} 

其他资源:

希望我已经简单了。而且我没有回答错误的问题。

于 2013-09-20T15:11:00.800 回答
2

this和的问题that已经在别处得到了雄辩和简洁的回答,所以我将回答你的问题:为什么要调用内部函数?

为什么不?

使用链接的答案作为起点:

$('#element').click(function(){
    // this is a reference to the element clicked on

    var that = this;

    $('.elements').each(function(){
        // this is a reference to the current element in the loop
        // that is still a reference to the element clicked on
    });
});

实例化一个新对象,传入您需要的所有变量,并手动构建适当的环境以循环某些元素有什么好处?您在这里拥有适当的环境,而范围正是您需要的地方。

如果您需要访问this内部范围内的变量,则需要重新分配它,因为它在内部范围内被重新使用。在这种情况下,有些人使用thatwhich 在我看来并不是很有启发性,但这只是将作用域传递给这些非常有用的临时内部作用域的一种方式。

这真的是关键,它是临时范围的变化。没有理由创建一个全新的范围、符号表等,当你在这里得到它时。

于 2013-09-20T15:13:55.267 回答
2

事件和计时器中回调的执行上下文更改。所以 this 的值变成了窗口。

将这个分配给那个(或自我)“那个”成为一个可以通过闭包访问的变量。'that' 将 'this' 赋予回调。

谷歌的一些东西:javascript 闭包、执行上下文、javascript self、javascript 计时器/事件上下文。

于 2013-09-20T15:14:31.023 回答
0

原因之一是,如果您将其设置为上下文,您可能希望在call任何apply其他对象上使用该方法。

    变量 obj = {
        名称:“富”
    },

    记录器=函数(名称){
        this.name = 名称;
        this.log = 函数 () {
            console.log(this.name)
        }
    };

    var bar = new logger('bar');
    bar.log(); // -> '酒吧'
    bar.log.call(obj); // -> 'foo'
于 2013-09-20T15:22:03.387 回答