Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Computed Property' in Vanilla Javascript Class

Tags:

javascript

The computed properties feature is common in popular JS frameworks (React, VueJS) but how do we implement this in vanilla JS?

Let's say that given a User class, with a dateOfBirth property, we would like to compute its age, is there a better way to perform this task than the code below?

function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    this.age = function() {
        return now() - this.dateOfBirth;
    }
}

var driver = new User('Steve', new Date('12 December, 1990'))
driver.age()

In the code above, we are retrieving the age value by calling a method. However, is it possible to be able to retrieve the value with just driver.age?

like image 358
puoygae Avatar asked Apr 14 '26 05:04

puoygae


2 Answers

Whether it's "better" or not is a matter of style/opinion, but if you want a property rather than a method, you can create an accessor property, in your case an accessor with a getter but no setter.

Making minimal changes to your code, you'd do it like this:

function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    Object.defineProperty(this, "age", {
        get() {
            return now() - this.dateOfBirth;
        }
    });
}

Live Example:

function now() { return Date.now(); }
function User(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;

    Object.defineProperty(this, "age", {
        get() {
            return now() - this.dateOfBirth;
        }
    });
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.log(steve.age);

You can define those more concisely using an object initializer (note that this example throws away the object created via new User and returns a different one instead, which doesn't have User.prototype as its prototype):

function User(name, dateOfBirth) {
    return {
        name,
        dateOfBirth,
        get age() {
            return now() - this.dateOfBirth;
        }
    };
}

Live Example:

function now() { return Date.now(); }
function User(name, dateOfBirth) {
    return {
        name,
        dateOfBirth,
        get age() {
            return now() - this.dateOfBirth;
        }
    };
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.log(steve.age);

I've also used the new (ES2015+) shorthand property syntax there for name and dateOfBirth.

This is also compatible with ES2015's class syntax:

class User {
    constructor(name, dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }
    get age() {
        return now() - this.dateOfBirth;
    }
}

Live Example:

function now() { return Date.now(); }
class User {
    constructor(name, dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }
    get age() {
        return now() - this.dateOfBirth;
    }
}

var steve = new User("Steve", new Date(1990, 11, 12));
console.log(steve.age);
like image 161
T.J. Crowder Avatar answered Apr 15 '26 18:04

T.J. Crowder


Yes. You can use a getter to return a computed value, like so:

class User {
  constructor(name, dateOfBirth) {
    this.name = name;
    this.dateOfBirth = dateOfBirth;
  }

  get age() {
    return new Date() - this.dateOfBirth;
  }
}

var driver = new User('Steve', new Date('12 December, 1990'));
console.log(driver.age);

More information here.

like image 42
Tim VN Avatar answered Apr 15 '26 18:04

Tim VN



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!