1

I'm trying to create a new object by using an already made object. This is what I am trying to achieve:

var obj = {"Name" : "Patrick", "Age": 25, "Country": "US"};
document.writeln(JSON.stringify(obj) + "<br />");

function Person(name, age, country) {
    this.name = name;
    this.age = age;
    this.country = country;
}

document.writeln(JSON.stringify(new Person(obj)));

https://jsfiddle.net/dotjz9tb/

As you can see, I am trying to create a new person called Patrick, aged 25, who happens to live in the US. My Person constructor takes a name, an age, and a country as parameters. However, my object has already been created from a previous function, so I would like to do new Person(obj) and it would create a new object based on obj's parameters.

I know I can do new Person(obj.name, obj.age, obj.country) but I would rather pass the constructor an object instead, while still being able to do new Person("Jack", 52, "UK").

Is such thing possible? Right now this is how it's really being created:

new Person(obj, undefined, undefined);
//or
{
    "name": {
        "Name":" Patrick","
         Age":25,
        "Country":"US"
    }
}

Meaning that age and country is set to nothing, while name is set to my object.

8
  • If constructor is function Person(obj) { this.name = obj.Name; this.age = obj.Age; this.country = obj.Country; } Commented May 30, 2016 at 8:06
  • @Rayon Then I would have to create a new constructor, which takes an object as well, right? Commented May 30, 2016 at 8:08
  • Or conditions inside it...Something like arguments.length ? Commented May 30, 2016 at 8:08
  • @Rayon How would such constructor look? One that takes both an object and 3 parameters. Commented May 30, 2016 at 8:09
  • you may abuse of the "...arguments" format: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , like this: jsfiddle.net/ghazkk1k Commented May 30, 2016 at 8:12

4 Answers 4

1

You have plenty of options here.

For example you could make your Person polymorphic on arguments it takes.

function Person(name, age, country) {
   if(arguments.length === 1 && typeof name === 'object') {
      var data = arguments[0];
      name = data.name; //etc
   } 
   //the rest of ctor code goes here
}

Or BETTER use factory function and keep your constructor code as simple is possible

function copyPerson(obj) {
   return new Person(obj.name, obj.age, obj.country);
}

//or even
Person.copy = function(obj) {
   return new this(obj.name, obj.age, obj.country)
}
Sign up to request clarification or add additional context in comments.

6 Comments

Creating a new function is kind of "meh". I'd rather stick with one constructor.
Well, it's up to you. But making your constructor code too complex is an antipattern. Factory functions is way more maintainable.
I completely agree, however, I would just like to do new Person() and parse it either an object or some parameters.
@Snorlax Then I'd recommend you to make your constructor take an object function Person(data) and move the other case to a separate functon.
I'm confused as to why you would put the BETTER answer last, or even include a WORSE answer.
|
1

In general it's better to avoid polymorphic interfaces. They end up being hard to maintain and document and remember.

In this case, I'd change the signature of the constructor to take an object, so

function Person(data) {
  Object.assign(this, data);
}

Now you can call it as

var patrick = new Person({name: 'Patrick', age: 25, country: 'US'});
var patrick2 = new Person(patrick);

1 Comment

Yeah this would be the best way to do it. Absolutely. Thanks.
0

This is what you could do to support both the input formats:

   function Person(name, age, country) {
        var obj;
        if(typeof(name) === 'object'){
          obj = name;
          name = obj.name;
          age = obj.age;
          country = obj.country;
        }
        this.name = name;
        this.age = age;
        this.country = country;
    }

4 Comments

So far this looks like the best option for me. Thanks.
Actually, it's not. It's best to avoid this kind of polymorphism. Instead, have a copy method on the class, as one answer suggested, or a clone method on the instances (in the prototype).
Yup I completely agree, however, I don't want to make it "more complex" than it needs to be.
Does anyone know if it's possible to, in this case, just name instead of this.name?
0
var Person = function(nameOrObj, age, country) {
  if (typeof nameOrObj === 'object') {
    this.name = nameOrObj.name
    this.age = nameOrObj.age
    this.country = nameOrObj.country
  } else {
    this.name = nameOrObj
    this.age = age
    this.country = country
  }
}

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.