Is there any way to invoke a method on each property instead of calling it on the obj and giving property as argument?
For example if I have an object like this:
const obj = { person: "John Smith" };
I know I can add a method like the following to the object:
addM(p) { return "Mr. " + p; }
and then call it as:
obj.addM(obj.person)
But is there any way to define the method that can be invoked like:
obj.person.addM()
or even better: obj.person.addM
Sorry if I simplified the question too much, I believe I can figure out how to code what I want in my project if I know the solution of this simple problem.
Actually I have some nested objects so please consider it in answering if necessary.
For example if I have:
const obj = {
person1: { firstName: "John", lastName: "Smith" },
person2: ...,
.
fullName() {
return this.firstName + this.lastName;
}
};
I want to invoke it as obj.person1.fullName
Bind prototypes of ES6 classes to any of your data, to handle your data in an OOP way:
class Person{
get fullName() {
return this.firstName + ' ' + this.lastName;
}
}
const obj = {
person1: { firstName: "John", lastName: "Smith" },
person2: { firstName: "Jane", lastName: "Doe" },
};
for(const prop in obj){
if(/^person\d+$/.test(prop)){
Object.setPrototypeOf(obj[prop], Person.prototype);
}
}
console.log(obj.person1.fullName);
console.log(obj.person2.fullName);
You can use Object.defineProperty, As the MDN explain: “The Object.defineProperty() static method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.”
In this example, use Object.defineProperty
for every obj child add a new property fullName
const obj = {
person1: { firstName: "John", lastName: "Smith" },
person2: { firstName: "Jane", lastName: "Doe" }
};
Object.keys(obj).forEach(key => {
Object.defineProperty(obj[key], 'fullName', {
get() {
return `${this.firstName} ${this.lastName}`;
}
});
});
console.log(obj.person1.fullName); // John Smith
console.log(obj.person2.fullName); // Jane Doe
put full name function in your object
const obj = {
Name: "John",
fullName() {
return `MR ${this.Name}`;
}
};
to call new Name
obj.fullName();
This does NOT answer your question and is purely an opinion: A common Javascript pattern is to not mix objects and data. Let data be data, and create functions (not methods) to act on that data, especially if you’re simply returning values rather than mutating the object itself. Otherwise, you could make
"John Smith"
a class with avalueOf
method, or modify the default String prototype to add methods to it, and deal with serializing/deserializing that data and/or the class constructor to create it.If
obj.person
is a string, you cannot (and definitely should not) add a.addM()
method to it. Ifobj.person
is an object consisting offirstName
andlastName
properties, it does make sense to add anaddM()
method it. If you have many objects, consider defining the method only once and adding it to each of the objects, or start usingclass
es.“I want to invoke it as
obj.person1.fullName
” – really? Didn’t you meanobj.person1.fullName()
?Please edit your question to clarify the above two points – remove the
{person: "John Smith"}
example if it doesn’t actually represent your real code@Bergi I have both situations in my project, strings and objects of strings as value . I know it is not good a idea to add a method to the String prototype but I supposed there could be a way to do it in an object. And about the
()
this could be achieved with a simple getter.