var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
你可以逐行解释这个代码吗?我明白了;;方法有一个可变计数器共享变量的评估,但它似乎是魔术无论如何因为我们说它在开始时为零
答案 0 :(得分:2)
Javascript完全是关于范围。该代码在名为Counter
的变量中定义了一个对象,但没有直接定义。它定义并调用一个返回对象的函数(使用方法increment()
,decrement()
和value()
)。该对象的范围是它创建的位置,因此它首先是匿名函数体,然后是全局命名空间。虽然闭包没有声明(存储)并且只调用一次,但范围仍然存在。这样对象就可以访问变量privateCounter
和方法changeBy()
。它是唯一可以访问这些成员的对象,因此它们被称为“私有”。
答案 1 :(得分:1)
var Counter = (function() {
这是名为Counter
的对象的创建。它是通过匿名自调用函数创建的。但由于该函数是自调用的,因此不建议使用大写名称。
var privateCounter = 0;
正在设置“私有”变量privateCounter
。从某种意义上说,它是私有的,你不能直接从外面访问它。它是在匿名函数的范围内创建的,它赋予它与包含函数 - Counter
的单独范围。这就是你无法从外部访问它的原因,例如Counter.privateCounter === undefined
。注意:每当您尝试从匿名函数访问this
时,结果将是window
对象,但您无法使用window.privateCounter
访问它。
function changeBy(val) {
privateCounter += val;
}
这是一种“私人”方法,Counter.changeBy() === undefined
。这与做var changeBy = function(val){}
相同。如果你想使属性或方法“公开”(可从外部访问),你必须像这样定义它们:
this.publicCounter = 0;
this.changeBy = function(val)...
这是通常的方法,当您的对象不是通过匿名函数创建时(请查看this
上面的注释),但在这种情况下,您可以像这样创建它们:
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
这些仍然是Counter
的“公共”方法,它们是Counter
对象范围的一部分。您可以像在警报中一样访问它们。
})();
这意味着该功能是自我调用的,例如它正在立即执行。
现在,在我开始之前......当您启动脚本时,会创建对象Counter
,因为它是一个自我调用的函数。这创建了该对象的范围和它的另一个范围的匿名函数(具有一个“私有”属性和一个“私有”方法)。三个返回的方法在Counter
的范围内,但是它们可以访问它的匿名函数的范围,即使该函数已经返回。这是因为这三种方法都指向该范围,它们仍然存在“一些业务”,因此垃圾收集器不会触及内部变量。返回匿名函数后,您可以访问其中的值的唯一方法是通过它返回的方法(如果有的话)。希望这很清楚。现在,让我们继续前进。
alert(Counter.value()); /* Alerts 0 */
这会调用value()
对象的Counter
方法。此方法进入已返回的匿名函数的范围,并返回局部变量的值。
Counter.increment();
Counter.increment();
再次调用对象的“公共”方法,该方法可以访问已返回的函数中的本地函数。
alert(Counter.value()); /* Alerts 2 */
和以前一样。但请注意privateCounter
在已返回的函数范围内。你不是在创建一个新的,只是通过一些具有专有权仍然可以看到它的方法访问旧的。
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
和以前一样。
基本上,就像调用一个勤杂工(对象)一样,勤杂工总是带着他的技能(“公共”方法和属性)和工具(“私人”方法和属性)。如果你需要完成某件事,请打电话给勤杂工并告诉他该做什么,使用哪种技能,但没有他就不能使用他的工具。他拥有自己的工具集,每次打电话给他都不会购买新套装。他的钳子和你上次踩到的那些旧的钳子相同。
答案 2 :(得分:0)
它很直接,我会尽量让它更清晰,'counter
'是一个对象,它包含三个函数(increment
,decrement
和值)和一个变量(privateCounter
)
在创建计数器时,privateCounter
设置为零作为初始化,这是显而易见的,但我认为让你很难将三个函数放在一起,但想想它将它们包含在'计数器'中,现在三个函数中的每一个都返回值(value()
),或者递增/递减一定数量。
现在最后6行应该有意义,第一行只复制初始值为零,然后我们递增两次,increment()
函数将内部值增加两次到2,当你执行value()
时它再次成为2,而decrement()
也是如此。我希望我的谈话对你有用。