javascript:class.property 与 class.prototype.property 模拟静态属性

标签 javascript static prototype

我一直在尝试在 javascript 中模拟静态属性。 在几个地方已经提到,class.prototype.property 在所有继承自该类的对象中都是静态的。但我的 POC 另有说法。请看一下:

使用 Class.prototype.property

//Employee class
function Employee() {
    this.getCount = function(){
        return this.count; 
    };      
    this.count += 1;
}
Employee.prototype.count = 3;

var emp = [], i;
for (i = 0; i < 3; i++) {
    emp[i] = new Employee();
    console.log("employee count is "+ emp[i].getCount());
}
/*Output is:
employee count is 4
employee count is 4
employee count is 4*/

我的问题 #1:如果这是静态的,那么 count 的值不应该是 4、5、6 等,因为所有对象都共享同一个 count 变量吗?

然后我用 Class.prototype 做了另一个 POC,我认为这是静态的。

使用 Class.property

//Employee class
function Employee() {
    this.getCount = function(){
        return Employee.count; 
    };      
    Employee.count++;
}
Employee.count = 3;

var emp = [], i;
for (i = 0; i < 3; i++) {
    emp[i] = new Employee();
    console.log("employee count is "+ emp[i].getCount());
}
/*Output is:
employee count is 4
employee count is 5
employee count is 6*/

我的问题 #2:我没有看到直接使用 class.property 的地方。 javascript 中的静态变量究竟是如何牢记我的上述代码的?

或者我在这里编码有误吗?这不是正确的认识吗?

最佳答案

My Question #1: If this were to be static, then shouldn't the value of count have been 4,5,6,etc as all the objects share the same count variable?

原型(prototype)属性在实例之间共享,但如果一个实例有自己的属性副本,它将使用它。分配给实例上的属性会为其提供自己的副本,因此它不再使用原型(prototype)。

+=++ 和类似的运算符会导致赋值,因此它们也会导致此行为。

考虑:

function Employee() {
}
Employee.prototype.count = 0;

在上面的代码中,Employee.prototype 在内存中有一个对象。一些 ASCII 艺术:

+−−−−−−−−−−−−−−−−−−−−+
| Employee.prototype |
+−−−−−−−−−−−−−−−−−−−−+
| count: 0           |
+−−−−−−−−−−−−−−−−−−−−+

Then we do this:

var e = new Employee();

现在内存中有第二个对象,它有对 Employee.prototype 的引用:

+−−−−−−−−−−−−−−−+
|     e         |
+−−−−−−−−−−−−−−−+          +−−−−−−−−−−−−−−−−−−−−+
| [[Prototype]] |−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−+          +−−−−−−−−−−−−−−−−−−−−+
                           | count: 0           |
                           +−−−−−−−−−−−−−−−−−−−−+

And if you query e.count:

console.log(e.count);

...因为 e 没有自己的名为 count 的属性,引擎会查看 e 的原型(prototype)来找到它,找到它,并使用该值。

但是,当我们这样做时:

e.count += 1; // Or more idiomatically, `++e.count;` or `e.count++;`

分配一个值给 e 实例上的 counte 现在拥有 自己的 count 副本:

+−−−−−−−−−−−−−−−+
|     e         |
+−−−−−−−−−−−−−−−+
| count: 1      |          +−−−−−−−−−−−−−−−−−−−−+
| [[Prototype]] |−−−−−−−−−>| Employee.prototype |
+−−−−−−−−−−−−−−−+          +−−−−−−−−−−−−−−−−−−−−+
                           | count: 0           |
                           +−−−−−−−−−−−−−−−−−−−−+

Now if you query e.count:

console.log(e.count);

...引擎在 e 上找到 count,但不查看原型(prototype)。

你可以在代码中看到这个效果:

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。它从对象中删除属性。

My Question #2: Nowhere I have seen class.property being used directly. How exactly are static variables made in javascript keeping in mind my above code?

两种方式:

  1. 正如您所做的那样,Employee.sharedProperty

  2. 通过在函数内定义整个“类”,并在该函数内使用局部变量:

    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

关于javascript:class.property 与 class.prototype.property 模拟静态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13486457/

相关文章:

c# - 如何使用 C# 代码(不是 python)将静态类(或静态方法)导入 IronPython(或 DLR)?

file - Angular2 中静态文件的默认路径是什么?

javascript - 干净的原型(prototype) fork (好主意?)

c# - Redis 之类的缓存服务器与静态变量

perl - 如何在没有 "called too early to check prototype"的情况下声明函数并递归使用它

javascript - Node 控制台中的 "Object"对象与 Web 控制台中的对象

javascript - 遍历 THREE.JS 中的 getObjectByName

javascript - 函数的目的仅返回 bool 值

javascript - 是否可以从未导入 withRouter 的文件设置组件路由?

javascript - 帮我创建正则表达式