我的问题 #1:如果这是静态的,那么 count 的值不应该是 4、5、6 等,因为所有对象都共享相同的 count 变量吗?
原型属性在实例之间共享,但如果一个实例有它自己的属性副本,它将使用它。分配给实例上的属性会给它自己的副本,因此它不再使用原型的。
, , 和类似的+=
运算++
符会导致赋值,因此它们也会导致这种行为。
考虑:
function Employee() {
}
Employee.prototype.count = 0;
在上面的代码中,内存中有一个对象用于Employee.prototype
. 一些 ASCII 艺术:
+−−−−−−−−−−−−−−−−−−−−−−−+
| Employee.prototype |
+−−−−−−−−−−−−−−−−−−−−−−−+
| 计数:0 |
+−−−−−−−−−−−−−−−−−−−−−−−+
然后我们这样做:
var e = new Employee();
现在内存中有第二个对象,它有一个对的引用Employee.prototype
:
+−−−−−−−−−−−−−−−−−+
| 电子|
+−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+
| [[原型]] |−−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+
| 计数:0 |
+−−−−−−−−−−−−−−−−−−−−−−−+
如果您查询e.count
:
console.log(e.count);
...由于e
没有自己的名为 的属性count
,因此引擎会查看e
的原型以找到它,找到它并使用该值。
但是,当我们这样做时:
e.count += 1; // Or more idiomatically, `++e.count;` or `e.count++;`
这会在实例上分配一个值。现在有自己的副本:count
e
e
count
+−−−−−−−−−−−−−−−−−+
| 电子|
+−−−−−−−−−−−−−−−−−+
| 计数:1 | +−−−−−−−−−−−−−−−−−−−−−−−+
| [[原型]] |−−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+
| 计数:0 |
+−−−−−−−−−−−−−−−−−−−−−−−+
现在,如果您查询e.count
:
console.log(e.count);
...引擎在count
上找到e
,并且不查看原型。
您可以在代码中看到这种效果:
function Employee() {
}
Employee.prototype.count = 0;
var e = new Employee();
console.log(e.hasOwnProperty('count')); // false
e.count += 1;
console.log(e.hasOwnProperty('count')); // true
console.log(e.count); // 1
console.log(Employee.prototype.count); // 0
这也很有趣:
var e = new Employee();
console.log(e.count); // 0
++Employee.prototype.count;
console.log(e.count); // 1
由于e
(还)没有自己的副本count
,如果我们实际增加 上的属性,无论我们直接( )或间接( )Employee.prototype
请求它,我们都会看到更新的值。Employee.prototype.count
e.count
关于此的最后说明:如果e
获得自己的属性副本,您可以再次将其删除:
var e = new Employee();
console.log(e.count); // 0, because it's using `Employee.prototype.count`
++e.count; // Now `e` has its own `count` property
console.log(e.count); // 1, `e`'s own `count`
delete e.count; // Now `e` doesn't have a `count` property anymore
console.log(e.count); // 0, we're back to using `Employee.prototype.count`
delete
会更恰当地称为remove
. 它从对象中删除属性。
我的问题 #2:我没有看到直接使用 class.property。记住我上面的代码,javascript中的静态变量究竟是如何制作的?
两种方式:
正如你所做的那样,Employee.sharedProperty
.
通过在函数中定义整个“类”,并在该函数中使用局部变量:
var Employee = (function() {
var sharedVariable = 0;
function Employee() {
++sharedVariable;
console.log("sharedVariable = " + sharedVariable);
}
return Employee;
})();
在该外部作用域函数中定义的所有函数都可以访问其中定义的局部变量。所以只有一个变量,在对创建Employee
.
然后,这段代码:
new Employee();
new Employee();
new Employee();
new Employee();
输出
1
2
3
4