The puted properties feature is mon 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 pute 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
?
The puted properties feature is mon 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 pute 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
?
-
There are no puted property names here. Better to put
age
on the prototype – Snow Commented May 15, 2019 at 8:26 -
yes you can using a
getter
– Jaromanda X Commented May 15, 2019 at 8:27 - Though, the code you've presented is very inplete – Jaromanda X Commented May 15, 2019 at 8:30
- related: stackoverflow./questions/4822953/… – Matt Ellen Commented May 15, 2019 at 8:36
2 Answers
Reset to default 5Whether 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 patible 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);
Yes. You can use a getter
to return a puted 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.