为什么要调用内部函数而不是方法?

时间:2013-09-20 14:55:56

标签: javascript function methods

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

方法是存储为对象属性的函数。因此,在方法中,this可用于修改或从包含它的对象中检索值。但是,如果将该方法作为函数调用,而不是作为对象的属性调用,那么this将绑定到全局,而不是绑定到对象。

解决方法是分配:

var that = this;

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

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

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

4 个答案:

答案 0 :(得分: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(在我的例子中)用来限定事物的范围。所以我可以访问其他范围内的对象范围。 说实话,我在其他地方使用过这个技巧(在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' ;
    }
} 

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

这可以用多长时间。

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

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' ;
    }
} 

其他资源:

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

答案 1 :(得分:2)

thisthat的问题已经得到了雄辩和简洁的回答elsewhere,所以我会回答你的问题:为什么要调用内部函数?

为什么不呢?

使用链接的答案作为跳出点:

$('#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变量,则需要重新分配它,因为它在内部范围内被重新使用。 在这种情况下,有些人使用that,这在我看来并不是很有启发性,但这只是将范围传递给这些非常有用的临时内部范围的方法。

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

答案 2 :(得分:2)

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

将此分配给那个(或自我)''成为可以通过闭包访问的变量。 'that'给回调提供'this'。

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

答案 3 :(得分:0)

其中一个原因是,如果您将其设置为上下文,则可能需要callapply该方法。

    var obj = {
        name: 'foo'
    },

    logger = function (name) {
        this.name = name;
        this.log = function () {
            console.log(this.name)
        }
    };

    var bar = new logger('bar');
    bar.log(); // -> 'bar'
    bar.log.call(obj); // -> 'foo'