1

What I have

I was defining some constructor-style functions statically in my code, and everything else was working fine.

As things got bigger, I wanted to define the constructor-style functions dynamically, based in my entities names.

The following two snippets of code show the problem that I've found. I would expect they to work exactly the same, but they don't.

Snippet 1:

var model = {};

// base constructor
model.Create = function(data, entity) {
    console.log("Inside Create, 'this' is", this, 'and entity is', entity);
    // initialization logic ...
}

// a constructor for each entity
model.constructors = {};
model.constructors.Country = function(data) {
    var entity = 'Country';
    console.log('Inside constructor', entity);
    model.Create.call(this, data, entity);
}
model.constructors.State = function(data) {
    var entity = 'State';
    console.log('Inside constructor', entity);
    model.Create.call(this, data, entity);
}

var br = new model.constructors.Country({name:'Brazil'});
var rs = new model.constructors.State({name:'Rio Grande do Sul'});
console.log(br);
console.log(rs);

The output:

Inside constructor Country

Inside Create, 'this' is model.constructors.Country {} and entity is Country

Inside constructor State

Inside Create, 'this' is model.constructors.State {} and entity is State

model.constructors.Country {}

model.constructors.State {}

Snippet 2:

var model = {};

// base constructor
model.Create = function(data, entity) {
    console.log("Inside Create, 'this' is", this, 'and entity is', entity);
    // initialization logic ...
}

// a constructor for each entity
model.constructors = {};
var entity;
entity = 'Country';
model.constructors[entity] = function(data) {
    console.log('Inside constructor', entity);
    model.Create.call(this, data, entity);
}
entity = 'State';
model.constructors[entity] = function(data) {
    console.log('Inside constructor', entity);
    model.Create.call(this, data, entity);
}

var br = new model.constructors.Country({name:'Brazil'});
var rs = new model.constructors.State({name:'Rio Grande do Sul'});
console.log(br);
console.log(rs);

The output:

Inside constructor State

Inside Create, 'this' is model.constructors.(anonymous function) {} and entity is State

Inside constructor State

Inside Create, 'this' is model.constructors.(anonymous function) {} and entity is State

model.constructors.(anonymous function) {}

model.constructors.(anonymous function) {}

I can't understand why using model.constructors.Country is producing a different result than using model.constructors['Country'], or what else can I be doing wrong.

Examining model.constructors in both cases produced the same output:

Object {Country: function, State: function}

What I need

I need the result of snippet 1, but using an approach like snippet 2, since I would be iterating over an array of entity names.

More exactly, I would need to work with it like this:

var model = {};
model.entities = ['Country', 'State'];

// base constructor
model.Create = function(data, entity) {
    console.log("Inside Create, 'this' is", this, 'and entity is', entity);
    // initialization logic ...
}

// a constructor for each entity
model.constructors = {};
for (var i in model.entities) {
    var entity = model.entities[i];
    model.constructors[entity] = function(data) {
        console.log('Inside constructor', entity);
        model.Create.call(this, data, entity);
    };
}


var br = new model.constructors.Country({name:'Brazil'});
var rs = new model.constructors.State({name:'Rio Grande do Sul'});

but having the code producing the same result as snippet 1.

So:

  1. How can I get this to work?
  2. Why does snippet 2 works differently than snippet 1?
  3. In snippet 2 output, what was referencing that "State" string that was printed twice in the log "[...] and entity is State"?
Community
  • 1
  • 1
Rafael Eyng
  • 4,720
  • 2
  • 33
  • 34
  • 1
    You have only a single `entity` variable in your snippets 2 and 3 that is shared between the constructors, and takes the value `'State'` before you call them. Use closures! – Bergi Sep 18 '14 at 12:07
  • The question I linked as a duplicate explains it quite well I think. You can use an IIFE as the body of your loop. – Bergi Sep 18 '14 at 12:23
  • @Bergi I can't see how would I pass my data parameter. – Rafael Eyng Sep 18 '14 at 12:28
  • 1
    `data` is still the parameter of the (*returned*) constructor function – Bergi Sep 18 '14 at 12:30
  • I think I got it. Still have to figure out how to use IIFE. I wouldn't find the answer you suggested because I wouldn't know what to search for exactly. – Rafael Eyng Sep 18 '14 at 12:42
  • That's why I linked the other question… See for example [this answer](http://stackoverflow.com/a/19324832/1048572) to it – Bergi Sep 18 '14 at 12:48
  • Point is, in this simple example it seems to work, in my complete real situation, it doesn't. I'll check it again, and edit the question as needed. – Rafael Eyng Sep 18 '14 at 13:01
  • Yes, please edit your question to include your approach, and I'll gladly reopen and answer it :-) Maybe also have a look [over here](http://stackoverflow.com/a/25267864/1048572) – Bergi Sep 18 '14 at 13:02

0 Answers0