Ali
Ali

Reputation: 267059

Associative arrays in javascript

I have this object:

function formBuddy()
{
    var fields = new Array();
    var labels = new Array();
    var rules = new Array();
    var count=0;

    this.addField = function(field, label, rule)
    {
        fields[count] = field;
        labels[field] = label;
        rules[field] = rule;
        count = ++count;
    }
}

Its used in this way:

var cForm=new formBuddy();
cForm.addField("c_first_name","First Name","required");
cForm.addField("c_last_name","Last Name","required");

The problem is, in the addField() function the fields array is being set correct (perhaps because a numerical index is being used to refer to it) but the other 2 arrays (labels and rules) aren't being touched at all. Doing a console.log shows them as empty in firebug.

What do I need to change to make them work? I'd still like to refer to the rules and labels by the string index of the field.

Upvotes: 2

Views: 4223

Answers (4)

Is this an alternative to what you are seeking ? Try it.

<script type="text/javascript">"use strict";
  function formBuddy() {
      this.fields = new Array();
      this.labels = new Array();
      this.rules = new Array();
      this.count=0;

      this.addField = function(field, label, rule)
      {
          this.fields[this.count] = field;
          this.labels[field] = label;
          this.rules[field] = rule;
          this.count++;
      }
  }

  var cForm = new formBuddy();

  // FILLING IN THE DATABASE
  cForm.addField("c_first_name","Diasoluka","duplicated");
  cForm.addField("c_Middle_name","Nz","inspect");
  cForm.addField("c_last_name","Luyalu","mandatory");
  cForm.addField("c_first_name","Diasoluka","duplicated");


  console.log(`ACCESSING EACH PROPERTY INDIVIDUALLY\n,${'.'.repeat(31)}`);

  let el=Object.entries(cForm.fields); // DESTRUCTURING
      console.log(Object.is(el,Object.entries(cForm.fields)));
      // false

  const [f1,f2,f3] = el; // DESTRUCTURING=DÉCOMPOSITION
  console.log("FIELDS:\n",f1," | ",f2," | ",f3,"\n\n");
  // FIELDS:
    // Array [ "0", "c_first_name" ]
    // Array [ "1", "c_Middle_name" ]
    // Array [ "2", "c_last_name" ]

  let labels = Object.entries(cForm.labels); // DESTRUCTURING
  const [l1,l2,l3] = labels; // DESTRUCTURING
  console.log("LABELS:\n",l1," | ",l2," | ",l3,"\n\n");
  // LABELS:
    // Array [ "c_first_name", "Diasoluka" ]
    // Array [ "c_Middle_name", "Nz" ]
    // Array [ "c_last_name", "Luyalu" ]

  let rules = Object.entries(cForm.rules); // DESTRUCTURING
  const [r1,r2,r3] = rules; // DESTRUCTURING
  console.log("RULES:\n",r1," | ",r2," | ",r3,"\n\n");
  // RULES:
    // Array [ "c_first_name", "duplicated" ]
    // Array [ "c_Middle_name", "inspect" ]
    // Array [ "c_last_name", "mandatory" ]


  console.log(`PAESING THE DATABASE =\nACCESSING ALL THE FIELDS AT ONCE\n,${'.'.repeat(31)}`);

  for(let key in cForm.fields){
    let el=cForm.fields[key]; // ASSIGNMENT=AFFECTATION
        console.log(Object.is(el,cForm.fields[key]));
        // true true true true

    console.log(`${el} // ${cForm.labels[el]} // ${cForm.rules[el]}\n`);
  }
  // c_first_name // Diasoluka // duplicated
  // c_Middle_name // Nz // inspect
  // c_last_name // Luyalu // mandatory
  // c_first_name // Diasoluka // duplicated


  console.log("\n");


  console.log(`THE INNER STRUCTURE OF OUR cForm OBJECT\n,${'.'.repeat(31)}`);
  console.log(Object.entries(cForm)); // DESTRUCTURING
  // (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
    // 0: (2) ['fields', Array(4)]
    // 1: (2) ['labels', Array(0)]
    // 2: (2) ['rules', Array(0)]
    // 3: (2) ['count', 4]
    // 4: (2) ['addField', ƒ]
    // length: 5
    // [[Prototype]]: Array(0)
</script>

Upvotes: 0

Christoph
Christoph

Reputation: 169553

fields should be an array, whereas labels and rules should be objects as you want to use strings as keys. Also, addField() is the same for each instance of FormBuddy() (names of constructor functions should be capitalized) and should reside in the prototype, ie

function FormBuddy() {
    this.fields = []; // this is the same as `new Array()`
    this.labels = {}; // this is the same as `new Object()`
    this.rules = {};
}

FormBuddy.prototype.addField = function(field, label, rule) {
    this.fields.push(field);
    this.labels[field] = label;
    this.rules[field] = rule;
};

You can access the labels/rules via

var buddy = new FormBuddy();
buddy.addField('foo', 'bar', 'baz');
alert(buddy.labels['foo']);
alert(buddy.rules.foo);

Just to further enrage Luca ;), here's another version which also dosn't encapsulate anything:

function FormBuddy() {
    this.fields = [];
}

FormBuddy.prototype.addField = function(id, label, rule) {
    var field = {
        id : id,
        label : label,
        rule : rule
    };

    this.fields.push(field);
    this['field ' + id] = field;
};

FormBuddy.prototype.getField = function(id) {
    return this['field ' + id];
};

var buddy = new FormBuddy();
buddy.addField('foo', 'label for foo', 'rule for foo');

It's similar to Gumbo's second version, but his fields object is merged into the FormBuddy instance. An array called fields is added instead to allow for fast iteration.

To access a field's label, rule, or id, use

buddy.getField('foo').label

To iterate over the fields, use

// list rules:
for(var i = 0, len = buddy.fields.length; i < len; ++i)
    document.writeln(buddy.fields[i].rule);

Upvotes: 2

Gumbo
Gumbo

Reputation: 655189

Use objects instead:

function formBuddy()
{
    var fields = {};
    var labels = {};
    var rules = {};
    var count = 0;

    this.addField = function(field, label, rule)
    {
        fields[count] = field;
        labels[field] = label;
        rules[field] = rule;
        count++;
    }
}

But as Christoph already mentioned, I would store this information in a single data structure too. For example:

function formBuddy() {
    var fields = {};
    this.addField = function(name, label, rule) {
        fields[name] = {
            name: name,
            label: label,
            rule: rule
        };
    };
    this.getField = function(name) {
        return fields[name];
    };
}

var cForm=new formBuddy();
cForm.addField("c_first_name","First Name","required");
cForm.addField("c_last_name","Last Name","required");
alert(cForm.getField("c_last_name").label);

Upvotes: 8

Luca Matteis
Luca Matteis

Reputation: 29267

Arrays are treated as Objects in Javascript, therefore your piece of code works, it's just that firebug's console.log isn't showing you the "Objects" inside the array, rather just the array values ...

Use the for(var i in obj) to see what objects values the Array contains:

function formBuddy() {
    var fields = new Array();
    var labels = new Array();
    var rules = new Array();
    var count=0;

    this.addField = function(field, label, rule)
    {        
        fields[count] = field;
        labels[field] = label;
        rules[field] = rule;
        count = ++count;

        for(var i in labels) {
            console.log(labels[i]);
        }
        for(var i in rules) {
            console.log(rules[i]);
        }

        console.log(labels.c_last_name);
        // or
        console.log(labels["c_last_name"]);
    }
}

var cForm = new formBuddy();
cForm.addField("c_last_name","Last Name","required");

Upvotes: 0

Related Questions