2009-02-22 7 views
2

У меня есть этот объект:Ассоциативные массивы в JavaScript

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; 
    } 
} 

Его использовали таким образом:

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

Проблема, в функции addField()fields массив создается правильно (возможно, из-за для обращения к нему используется числовой индекс), но другие 2 массива (labels и rules) вообще не касаются. Выполнение console.log показывает их как пустые в firebug.

Что мне нужно изменить, чтобы заставить их работать? Я все равно хотел бы ссылаться на правила и метки по строковому индексу поля.

+0

Javascript не имеют собственные ассоциативные массивы, только объекты. Объекты имеют свойства, а имя свойства всегда является строкой. Даже индекс массивов преобразуется в строку до того, как произойдет «массивная магия». – some

ответ

8

Использование объектов вместо:

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++; 
    } 
} 

Но Christoph already mentioned, я бы хранить эту информацию в единой структуре данных тоже. Например:

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); 
+0

Действительно, javascript не имеет ассоциативных массивов.Ассоциативный массив - это объект. –

+0

Если я сделал правила [field], тогда (где поле - это строка, содержащая имя поля), будет ли она работать? –

+0

Зачем использовать объекты, когда вы можете просто увеличить массивы? -1. –

0

Массивы рассматриваются как объекты в Javascript, поэтому ваш кусок кода работает, это просто, что Firebug, console.log не показывая вам «объекты» внутри массива, а только значения массива .. .

используйте for(var i in obj), чтобы увидеть, какие объекты значения массива содержит:

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"); 
+0

Что мне нужно сделать, так это уметь возвращать правило поля. Например, правило = правила [поле], или правило = rules.field. Это не работает в настоящее время с кодом массивов и дает мне ошибку. –

+0

Работает для меня console.log (метки ["c_last_name"]); или console.log (labels.c_last_name); –

+0

вы должны проверить 'hasOwnProperty()' при переходе по свойствам - некоторое время назад было модно расширять 'Array.prototype' – Christoph

2

fields должен быть массивом, в то время как labels и rules должны быть объекты, как вы хотите использовать строки как ключи. Кроме того, addField() одинакова для каждого экземпляра FormBuddy() (имена функций конструктора должны быть капитализированы) и должны находиться в прототипе, т.е.

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; 
}; 

Вы можете получить доступ к ярлыкам/правила через

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

Просто дальше бесить Лука;), вот еще одна версия, которая также dosn't ничего инкапсулировать:

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'); 

Это похоже на вторую версию Гумбо, но его объект fields объединен с экземпляром FormBuddy. Вместо этого добавляется массив, называемый fields, чтобы обеспечить быструю итерацию.

Для доступа этикетки, правило или идентификатора поля, используйте

buddy.getField('foo').label 

Для перебирать полей используйте

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

Забыл прототип? –

+0

@Luca: Да - исправлено;) – Christoph

+0

Я думаю, что он/она хочет, чтобы свойства были частными, я мог ошибаться. –