我知道这个主题在这里得到了很多处理,但我在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/
我会非常高兴:
非常感谢你!
答案 0 :(得分:1)
感谢@elclanrs提醒我内心化和遗忘的事情......
重要的是that
......是不必要的。
我将引用一篇@elclanrs在上述帖子评论中链接的文章:
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 );
}
}
首先,让我们解决这个问题:这个例子很愚蠢,但你会看到喜欢这个 - 在其他范围内定义的函数 - 一直都是这样。
以下是需要注意的重要事项:
.
表示法)当以这种方式调用函数时,引擎必须找出要在函数范围内分配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
对象(add
,multiple
,equals
)的每个方法都引用相同的全局变量
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
});