Reputation: 31
When I create a class in JavaScript like this one:
class Person {
_firstName = "";
_lastName = "";
constructor(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
}
get firstName() {
return this._firstName;
}
get lastName() {
return this._lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
let me = new Person("John", "Doe");
It creates a variable me that is an instance of Person. Its prototype has some functions whose names are “fullName” and “get firstName” (plus other functions)
I can call the function fullName by its name using:
me[“fullName”]();
John Doe
However, calling the getter function by its name throws an error:
me[“get firstName”]();
Uncaught TypeError: me.get firstName is not a function
Why does this behavior happen?
EDIT: Thanks for the replies. I know I can and should access it as a property. But I'd like to understand why accessing it by its name with the brackets notation does not work. Does that mean JavaScript has different kinds of functions since a behavior that works for one function does not work for another function (when it has a space in its name / is a getter or setter)?
Upvotes: 2
Views: 492
Reputation: 351183
When a function is assigned to a variable or as a property value (maybe a getter), there are two names involved:
These names are different entities and don't necessarily have to be the same.
Here is a simple object with property "a" that has as value a function whose name is "b":
let obj = {
a: function b() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", obj.a.name); // "b"
Now when the function does not get an explicit name, it is given one:
let obj = {
a() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", obj.a.name); // "a"
This may give the false impression that both names are one and the same string, but this cannot be true as the same function object might be assigned to different properties:
let obj = {
a() { }
};
obj.c = obj.a;
console.log("property: ", Object.keys(obj)[1]); // "c"
console.log("function: ", obj.c.name); // "a"
The situation with a getter can be confusing, because the expression obj.a.name
will not retrieve the name of the function, but will invoke the getter and then try to access the name
property of the returned value.
To still get the name of the getter function, you can use Object.getOwnPropertyDescriptor
as follows:
let obj = {
get a() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", Object.getOwnPropertyDescriptor(obj, "a").get.name); // "get a"
This is how a getter's function name is set by default. You can however set it explicitly to your desire using Object.defineProperty
as follows:
let obj = {};
Object.defineProperty(obj, "a", {
get: function b() {},
enumerable: true
});
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", Object.getOwnPropertyDescriptor(obj, "a").get.name); // "b"
A property name does not necessarily match with the name of the function that might be the property's value.
A property is identified by property name, not by the name of the function that might be associated with it.
The function object, that serves as a getter property, can be accessed with Object.getOwnPropertyDescriptor(object, propertyName).get
Upvotes: 2
Reputation: 76
When doing this:
get firstName() {
return this._firstName;
}
it´s defining a property and the you have to call it over:
me.firstName;
doing it like this:
getFirstName() {
return this._firstName;
}
is really defining a getter function and you can call it like this:
me.getFirstName();
Maybe this is helpfull: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/get
Upvotes: 0
Reputation: 16266
You should access it as a normal property like this:
me["firstName"];
But, if you know already the name, you could access the firstName value like this:
me.firstName
Typically, you use the first form if you want to access a property of an object using a variable like this:
const person = new Person("John", "Doe");
const propertyName = "firstName";
const firstName = person[propertyName];
If you want to know more about getter and setters check out this and this.
Follows a fully working example:
class Person {
_firstName = "";
_lastName = "";
constructor(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
}
get firstName() {
return this._firstName;
}
get lastName() {
return this._lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const me = new Person("John", "Doe");
const propertyName = "firstName";
console.log(me["firstName"])
console.log(me.firstName)
console.log(me[propertyName])
Upvotes: 1