【问题标题】:Javascript - increment class variable on every instanceJavascript - 在每个实例上增加类变量
【发布时间】:2020-01-04 18:08:43
【问题描述】:

让我知道这是否已经被问过。如何在每个实例上增加一个类变量?假设我有以下 Key 类,我想在创建实例时增加 key 变量,我尝试过:

class Key{
    key = 1
    constructor(){
        this.key = key
        Key.key++
    }

    print_key(){
        console.log(this.key)
    }
}

然后我打印几个实例:

key1 = new Key()
key2 = new Key()
key3 = new Key()

key1.print_key()
key2.print_key()
key3.print_key()

期望的结果是:

1
2
3

上面的代码不起作用,我找不到具体的答案,或者某些答案似乎对我不起作用。

【问题讨论】:

  • 这似乎是静态而不是实例属性的好用途。

标签: javascript class ecmascript-6 es6-class


【解决方案1】:

您可以使用静态属性来记住已经创建了多少个,然后在初始化 key 实例属性时使用它。 static class properties 仍然是第 3 阶段,所以它们还没有在规范中,但它们已经相当远了。

class Key {
    // The static property
    static lastKey = 0;
    
    // The instance property using the class fields proposal syntax
    // Note I didn't initialize it with 1, that's a bit misleading.
    key;
    
    constructor() {
        // Increment and assign
        this.key = ++Key.lastKey;
    }

    print_key() {
        console.log(this.key)
    }
}

const key1 = new Key();
const key2 = new Key();
const key3 = new Key();

key1.print_key();
key2.print_key();
key3.print_key();

但请注意,任何地方的任何代码都可以分配给 Key.lastKey 以更改它下次使用的值。

如果您想将其设为私有,您可以使用private static class field。这些也处于第 3 阶段,但还很远:

class Key {
    // The static property
    static #lastKey = 0;

    // The instance property using the class fields proposal syntax
    // Note I didn't initialize it with 1, that's a bit misleading.
    key;

    constructor() {
        // Increment and assign
        this.key = ++Key.#lastKey;
    }

    print_key() {
        console.log(this.key)
    }
}

const key1 = new Key();
const key2 = new Key();
const key3 = new Key();

key1.print_key();
key2.print_key();
key3.print_key();

Stack Snippets 没有插件来处理这个问题,所以here's an example on the Babel REPL

在该代码中,只有 Key 代码可以访问#lastKey

或者只使用范围函数:

const Key = (() => {
    // Only code within this anonymous function has access to `lastKey`
    let lastKey = 0;
    return class Key {
        // The instance property using the class fields proposal syntax
        // Note I didn't initialize it with 1, that's a bit misleading.
        key;

        constructor() {
            // Increment and assign
            this.key = ++lastKey;
        }

        print_key() {
            console.log(this.key)
        }
    }
})();

const key1 = new Key();
const key2 = new Key();
const key3 = new Key();

key1.print_key();
key2.print_key();
key3.print_key();

这仍然依赖于class fields proposal(正如您在问题中所做的那样)。如果您想要一个 ES2015 解决方案,只需删除key 声明:

const Key = (() => {
    // Only code within this anonymous function has access to `lastKey`
    let lastKey = 0;
    return class Key {
        constructor() {
            // Increment and assign
            this.key = ++lastKey;
        }

        print_key() {
            console.log(this.key)
        }
    }
})();

const key1 = new Key();
const key2 = new Key();
const key3 = new Key();

key1.print_key();
key2.print_key();
key3.print_key();

【讨论】:

  • 所以我尝试了您发布的第一个代码 sn-p,但在“静态 lastKey = 0”行上出现“意外令牌”错误,我是否遗漏了什么?该代码似乎可以在 Stack Overflow 上运行。
  • @chacha - 我应该更清楚上述哪些部分依赖于正在进行的提案。上面使用的所有提议都已经很长了,但它们都仍处于第 3 阶段(等待多个生产实施)。我已经更新了答案以标记每个人具体使用什么,并在最后展示一个纯 ES2015(和 ES2019)解决方案。
  • 那是清晰简洁的。该代码有效。谢谢!
【解决方案2】:

您可以在类之外存储对密钥的引用。例如,整个脚本可能如下所示:

var key = 1
class Key {
    constructor(key){
        this.key = key
    }

    print_key(){
        console.log(this.key)
    }
}
key1 = new Key(key)
key++
key2 = new Key(key)
key++
key3 = new Key(key)
key++
key1.print_key()
key2.print_key()
key3.print_key()

另一种方法可能是保留一个键数组。需要注意的重要一点是,一个对象的实例对同类型对象的其他实例一无所知——它不知道存在多少同类型对象的实例,因此该值必须存储在其他地方。您的代码将 'key' 的值设置为 1,但该代码行用于每个新实例,而不仅仅是第一个实例。这有帮助吗?

【讨论】:

    【解决方案3】:

    您想要的结果不正确,因为 javascript 中的每个类都有自己的上下文 this 并且每次创建新的类实例时,例如:

    const key1 = new Key()

    您创建新的上下文。

    因此,如果您需要多次递增并且想要使用类,则需要为您的类添加方法。

    class MyClass {
      constructor() {
        this.value = 1;
      }
      // method for increment value
      increment() {
        this.value+=1;
      }
      
      // method for print your value
      print() {
        console.log(this.value)
      }
    }
    
    const myClass = new MyClass();
    
    myClass.print(); // print initial value
    myClass.increment(); // print initial value
    myClass.print(); // print incremented value

    更多详情可以阅读Doc

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 2017-04-01
      • 2020-06-14
      • 2022-09-24
      相关资源
      最近更新 更多