Javascript关闭&在特定的例子中,“那个”而不是“这个”

时间:2014-02-26 01:30:07

标签: javascript jquery design-patterns closures this

我知道这个主题在这里得到了很多处理,但我在Pluralsight JS设计模式课程中看到了这个具体的例子,我很乐意帮助你了解那里的闭包。

这是一个例子:

var Calc = function(start) {
    var that = this;

    this.add = function(x) {
        start = start + x;
        return that;
    };

    this.multiply = function(x) {
        start = start * x;
        return that;
    };

    this.equals = function(callback) {
        callback(start);
        return that;
    };
}

new Calc(0)
    .add(1)
    .add(2)
    .multiply(3)
    .equals(function(result){
        console.log(result); // returns 9
    });

这是JSFiddle链接:http://jsfiddle.net/3yJ8Y/5/

我会非常高兴:

  1. 理解“那”使用。为什么我们需要这个特定的 例?它与“this”相同。你能举例说明我们什么时候需要做“var that = this”吗?
  2. 了解从对象创建函数的这种方式。为什么我们必须使用“this”然后使用.functionName?像this.add = ...
  3. 这个非常具体的闭包示例的详细而广泛的解释。
  4. 非常感谢你!

2 个答案:

答案 0 :(得分:1)

感谢@elclanrs提醒我内心化和遗忘的事情......

重要的是that ......是不必要的。

我将引用一篇@elclanrs在上述帖子评论中链接的文章:

Scope In Javascript

  

JavaScript为函数调用建立一个执行上下文,将其设置为前一个“。”之前引用的对象。

因为在点之前使用外部Calc调用每个方法,所以该方法中的this值被指定为外部对象。

反过来,外部对象是它自己全新的自包含范围,因为它是使用new关键字创建的:

  

执行new [Calc] ()时,会在后台透明地创建一个全新的对象。调用[Calc],并将其this关键字设置为引用该新对象。

Scope in Javascript, again, with my edits in brackets)。

现在你可能想知道,“这是怎么回事:

.add(1)
.add(2)
.multiply(3)

......保持正确的范围?你说过在这种情况下.作为this变量传入之前的任何内容!?

绝对正确,在这种情况下,每个方法都返回this,这允许方法链接。 (他们实际上正在返回that,但我们已经确定在这种情况下这是一个不必要的变量。)

为什么要使用that

首先,我要说我更喜欢var self = this而不是var that = this,但无论哪种方式都存在论据。

让我们随意修改对象,使其具有如下所示的方法:

this.getInternalThis = function(){
    var internalThis = function(){
        console.log( this );
    }
}

首先,让我们解决这个问题:这个例子很愚蠢,但你会看到喜欢这个 - 在其他范围内定义的函数 - 一直都是这样。

以下是需要注意的重要事项:

  1. 它是按名称调用的,仅此而已(例如,没有带前缀的.表示法)
  2. ......就是这样!
  3. 当以这种方式调用函数时,引擎必须找出要在函数范围内分配this的内容。它默认为window。 如果您要运行此代码,则会在控制台中获得Window

    现在,如果我们希望内部函数调用中的this成为this的调用值,该怎么办? 情况是您需要that变量的地方。我们可以将函数修改为:

    this.getInternalThis = function(){
        var that = this,
            internalThis = function(){
                console.log( that );
            };
    }
    

    现在,当您运行此方法时,您将在控制台中获取调用对象的值 就我而言,它是Object { add=function(), multiply=function(), equals=function(), getInternalThis=function()}

    有时,这就是您需要或期望的内容,因此您将使用var that = this声明。

    使用this.定义方法

    正如我前面提到的那样:

      

    因为在点之前使用外部Calc调用每个方法,所以该方法中的this值被指定为外部对象。

    请记住,this范围内的Calc()是对 new Calc对象的引用,因此每个方法都被赋予Calc对象作为{{{I}的值1}}(记住,它在this之前!)当他们从该上下文进入新范围时。

    希望这能为您提供有关JavaScript范围和.分配方式的一些信息。

答案 1 :(得分:0)

start成为Calc对象

的全局变量

Calc对象(addmultipleequals)的每个方法都引用相同的全局变量

new Calc(0)            // <- sets start to 0
    .add(1)            // calls add() <- sets start to 1
    .add(2)            // calls add() <- sets start to 3
    .multiply(3)       // calls multiple() <- sets start to 9
    .equals(function(result){
        console.log(result); // returns 9
    });