17

I know I can init an array of JS objects like this:

var things = [
  {
    prop1: 'foo',
    prop2: 'bar'
  },
  {
    prop1: 'foo',
    prop2: 'bar'
  }
];

I guess I would call these 'anonymous' types (sorry, I'm using C#/.NET language).

What if I want these to be of the same prototype? So I have defined a constructor:

var Thing = function Thing() {
};

Thing.prototype.prop1 = 'default value';
Thing.prototype.prop2 = 'default value';

Now I want both the items in my original code above to be Things. Is there a good way to do this?

If I were to guess, I would say maybe something like:

var things = [
  new Thing() {
    prop1: 'foo',
    prop2: 'bar'
  },
  new Thing() {
    prop1: 'foo',
    prop2: 'bar'
  }
];

Which is basically C# object initializer syntax. What I'm trying to avoid is:

var thing1 = new Thing();
thing1.prop1 = 'foo';
thing1.prop2 = 'bar';
var thing2 = new Thing();
thing2.prop1 = 'foo';
thing2.prop2 = 'bar';
var things = [thing1, thing2];

Edit:

I should also note that my prototypes also contain some functions that are shared. Also in actuality I have arrays nested 3 deep, so its something more like:

{
   [
    { 
      [
        {},
        {}
      ]
    },
    {
      [
        {},
        {}
      ]
    }
  ]
}

Which is why I as hoping to just init everything inline like this and not setting each property line by line.

0

4 Answers 4

13
var Thing = function(params) {
  this.prop1 = params.prop1;
  this.prop2 = params.prop2;
};

var things = [
  new Thing({
    prop1: 'foo',
    prop2: 'bar'
  }),
  new Thing({
    prop1: 'foo',
    prop2: 'bar'
  }),
];
Sign up to request clarification or add additional context in comments.

1 Comment

Marking this as the answer because it worked best in my situation. It also allowed me to do optional properties, like: function Thing (params) { this.name = params.hasOwnProperty("name") ? params.name : "some default"; }
11

You are not making use of your 'constructor'. Its preferred to initialize values IN YOUR CONSTRUCTOR:

var Thing = function Thing(prop1, prop2) {
    this.prop1 = prop1;
    this.prop2 = prop2;
};

and then do:

var thing1 = new Thing("foo", "bar");
var thing2 = new Thing("foo", "bar");

2 Comments

I started down this path, but it gets a little odd because some of my properties are also arrays, so I end up with something like: new One("foo", [new Two([new Three(), new Three()]), new Two([new Three(), new Three()])], "bar") which just looks ugly. I think you are probably right though. I guess I was just trying to retain the property names, for readability.
@CodingWithSpike, if you're going through the trouble of making a new class, you should probably be sure that you've got a use case for methods on that class. Otherwise, you're better off with object and array literals. Additionally, large amounts of static data are probably better left as a JSON data source.
1

In this cases I add a "config" method to the object:

function Thing() {
}
Thing.prototype.prop1 = 'foo';
Thing.prototype.prop2 = 'bar';
Thing.prototype.config = function(data) {
    for (var i in data)
        if (data.hasOwnProperty(i))
            this[i] = data[i];
}

var array = [
    new Thing().config({
        prop1: 'foobar',
        prop2: 'barfoo'
    })
];

3 Comments

Is there a difference between having a .config() and doing it in the constructor itself? function Thing(data) { for (var i in data) ... } which is basically @alcidesqueiroz answer.
Well, the main difference is than implementing it on the constructor executes the iteration over the object every time you create a Thing, doesn't matter if you need it or not, using .config() method you implicitly ask for it.
Also, you can add the method .config() to any existing class (but I don't recommend you to extend native Types)
0

The following may work, is this something you'd want to avoid also?

var thing1 = new Thing();
var thing2 = new Thing();

thing1.prototype = {
    prop1: "foo",
    prop2: "bar"
};

thing2.prototype = {
    prop1: "foo",
    prop2: "bar"
};

Another thing I can think of is making the constructor yourself so it allows something like the following:

var things = [
    new Thing({
        prop1: "foo",
        prop2: "bar"
    }),
    new Thing({
        prop1: "foo",
        prop2: "bar"
    })
];

3 Comments

Wouldn't that change the prototype that each object instance is based on? The prototype also has some shared functions, so wouldn't it loose those too?
@CodingWithSpike yeah it would =/
You cannot change the prototype of instances. Constructors have the .prototype property, who is referred to the hidden [[Protototype]] property of the objects created with this constructors. You cannot change this property (in a standard way), so what the first snippet is doing is adding a property called prototype to the instances who must be accessed by thing1.prototype.prop1 who has nothing to do with thing1.prop1

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.