1

Let me know if this has already been asked. How do I increment a class variable on every instance? Say I have the following Key class, I want to increment the key variable whenever an instance is created, I tried:

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

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

Then I print make a few instances:

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

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

The desired result would be:

1
2
3

Above code does not works and I couldn't find a concrete answer or some of the answers didn't really seem to work for me.

1
  • 3
    This seems like a good use for a static instead of an instance property. Commented Jan 4, 2020 at 18:10

3 Answers 3

12

You can use a static property to remember how many have already been created, then use that when initializing your key instance property. static class properties are still Stage 3 so they aren't in the spec yet, but they're fairly far along.

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();

Note, though, that any code anywhere can assign to Key.lastKey to change what value it will use next time.

If you want to make it private, you can use a private static class field. Those are also at Stage 3 but fairly far along:

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 don't have the plugin to handle that, so here's an example on the Babel REPL.

In that code, only Key code can access #lastKey.

Or just use a scoping function:

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();

That still relies on the class fields proposal (as you did in your question). If you want a pure ES2015 solution, just remove the key declaration:

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();

Sign up to request clarification or add additional context in comments.

3 Comments

So I tried the first code snippet you posted and I'm getting an 'Unexpected token' error on 'static lastKey = 0' line, am I missing anything? The code seems to work here on Stack Overflow.
@chacha - I should have been clearer about what parts of the above relied on in-progress proposals. All of the proposals used above are quite far along, but they're all still Stage 3 (waiting for multiple production implementations). I've updated the answer to flag up what specifically each one uses, and to show a pure ES2015 (and ES2019) solution at the end.
That was clear and concise. The code works. Thank you!
1

You could store a reference to the key outside of the class. For example the entire script might look like this:

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()

An alternative way to do this might be to keep an array of the keys. The important thing to note is that an instance of an object knows nothing about other instances of the same type of object - it has no idea how many instances of the same type of object exist, so that value must be stored somewhere else. Your code sets the value of 'key' to 1, but that line of code is used for every new instance, not just the first one. Does that help?

Comments

0

Your desired result is not correct, because every class in javascript have own context this and every time when you create new instance of class like:

const key1 = new Key()

you create new context.

So, if you need some increment many times and you want use class, you need add methods for your class.

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

For more details you can read Doc

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.