我正在阅读Stoyan Stefanov" Javascript Patterns"。我对私有静态成员部分感到困惑 - 它是如何工作的。
var Gadget = (function () {
var counter = 0;
return function () {
console.log(counter += 1);
};
}());
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
为什么"反击"成为静态会员?
非常感谢提前!
答案 0 :(得分:2)
Gadget
是对counter
的封闭。每当您致电Gadget
时,1
都会被添加到counter
。
可能更容易看到您是否将代码编写为
var counter = 0;
var Gadget = function () {
console.log(counter += 1);
};
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
代替。应该很清楚,只有一个counter
变量,并且只要调用Gadget
,它的值就会增加。
代码的不同之处在于它包含在IIFE中,因此除了从IIFE返回的任何其他函数(分配给{{{{}}之外的任何其他函数都无法访问counter
。 1}}),从而使Gadget
"私有"。
另请参阅:What is the (function() { } )() construct in JavaScript?
答案 1 :(得分:0)
它成为静态成员,因为它不会在对象之外进行修改。这不是动态的。
因此,它成为静态成员。
换句话说,在对象内部使用的所有变量,不是函数和属性,以及用于内部逻辑的变量都称为静态成员。
答案 2 :(得分:0)
原因是因为immediate函数返回的函数的闭包包括对所有Gadgets实例的同一计数器的引用。事情就是这样(粗略地):
当你打电话给新小工具()'返回一个Gadget实例。
一个。这个Gadget实例只是另一种调用函数的方法,该函数为' this'提供了一个空对象。并返回它。所以g1和g2是空白对象。
湾这意味着所有实例都会引用计数器'
答案 3 :(得分:0)
它是私有的,因为立即执行其定义从第1行开始的匿名函数创建的对象之外的任何内容都不能访问变量计数器。
它不是真正的静态,因为如果在内部作用域中定义了Gadget,那么一旦Gadget 和它拥有的所有Gadget对象,用于Counter的存储可能被垃圾收集已创建已被丢弃。但是当在顶层使用时,它在大多数情况下都表现得像静态。
令人困惑的是,之后的更完整示例中的此代码不会执行Stefanov所说的内容。
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
};
NewGadget.prototype.getLastId = function () {
return counter;
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
他写道:“因为我们为每个对象增加一个计数器,所以这个静态属性成为唯一标识用Gadget构造函数创建的每个对象的ID。”。那是错的。只有一个counter
,并且所有Gadget对象都有对它的引用。函数getLastId()
正如其名称所暗示的那样:获取最近发布的id,并且不在创建小工具时计数器的值。
因此,上面的示例运行,并生成注释所指示的结果。但是如果你试试
iphone.getLastId(); // 3
再一次,你得到3
- 计数器的当前值,不是创建iPhone
时的值。
为了获得具有唯一ID的每个Gadget的效果,我们可以为每个Gadget使用一个新变量,如下所示:
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
var myId = counter;
this.myUid = function () {
return myId;
};
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.myUid(); // 1
var ipod = new Gadget();
ipod.myUid(); // 2
var ipad = new Gadget();
ipad.myUid(); // 3
iphone.myUid(); // 1
请注意myId
肯定不是静态,即使我们使用与counter
相同的模式。但是,它是私人的。每个小工具都有一个单独的myId
,它不是Gadget对象的属性 - 它真的是隐藏的。但是对象的myUid
函数已关闭它。