领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

JavaScript中的记录集合

nixiaole 2024-11-25 15:42:31 知识剖析 16 ℃

概要

在这篇文章中:

我们研究了JavaScript Object对象及其用于处理关联数组的内置功能。

我们特别注意了数组数据(由数字索引)和对象属性(由键值索引)之间的差异。

关联数组的一项有用功能是,它允许以非常灵活的方式将参数数据传递给函数。

我们看到了如何创建构造函数,作为形式化对象中元素和进行初始化的方法。我们看到了如何向这样的记录添加方法(函数)。

最后,创建并访问了一个对象数组,将它们视为一组记录。

正文

当您需要跟踪简单的数字或字符串列表时,Array对象是您最直接的工具。正如我们在之前的EE文章中所见,典型的数组处理可能如下所示:

var aNames= [ "Adam", "Bill", "Carl" ]; // create an array

alert( aNames[0] ); // Adam  --  look it up by its index number

// iterate through them
for ( var j=0; j< aNames.length; j++ ) {
    alert( aNames[j] );  // 
}


但是JavaScript还支持关联数组(又名MapsDictionaries)-提供一种不仅可以通过位置,而且可以通过关联来访问列表项的方法

但是,这种支持可能无法完全按照您认为的方式工作...

// this seems reasonable...

var aNames= new Array();  
aNames[ "Anderson" ]= "Adam";
aNames[ "Browne"   ]= "Bill";
aNames[ "Crawford" ]= "Carl";

alert( aNames[ "Anderson" ] );  // shows Adam (as expected)

// ... but this might not seem reasonable:

alert( aNames.length ); // shows 0 !!! (why not 3?)


上面的代码创建一个Array,然后将任何东西都放到任何array元素中!
这是怎么回事:每个JavaScript变量(包括Array变量)都是一个具有Object对象基础功能的对象。它是支撑键/值对处理关联数组的基类。因此,例如:

var mapNames= {
   "Anderson" : "Adam",    // syntax is key:value
   "Browne"   : "Bill",
   "Crawford" : "Carl"
};
for ( var n in mapNames ) {        // show the keys and values
    alert( n+ "=" + mapNames[n] ); // Anderson=Adam, Browne=Bill, etc...
}


这些键/值对通常称为对象的属性
Object对象支持语法选项,该选项允许您同时定义键和值:

var mapNames= {
   "Anderson" : "Adam",    // syntax is key:value
   "Browne"   : "Bill",
   "Crawford" : "Carl"
};
for ( var n in mapNames ) {        // show the keys and values
    alert( n+ "=" + mapNames[n] ); // Anderson=Adam, Browne=Bill, etc...
}


在左边和是正确的。该值不必是字符串或其他简单值。它可以是一个数组,也可以是另一个具有自己的键/值对(属性)映射的对象。您可以根据需要使对象复杂。有关一些相关信息和示例,请参见JSON。

对象作为函数参数

这种灵活性使它对许多事情都非常有用,其中之一就是将数据传递给函数调用,使得函数可以按名称引用参数。您可能已经看过以下语法:

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


调用者创建一个匿名对象(键:值对的映射),然后被调用函数可以按名称访问值。请注意呼叫中使用的快捷方式:如果是文本字符串,则在标识属性时可以省略引号。

创建关联数组“记录”

您可以即时创建地图对象,一时兴起添加新属性。这种灵活性具有实际的编程缺点。例如:

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


如果您拼写错误的键名,那么您刚刚向对象添加了一个新属性。那可能不是您想要的!尽管不需要预先声明JavaScript关联映射,但这样做可以帮助您避免一些错误。让我们看一下一种“形式化”对象属性的方法。
通常情况下,您需要预定义记录-一种包含要包含在该对象中的所有数据的结构。您将希望能够引用该对象的定义,以便可以查看其所有属性(而且,一件事,请确保每次使用时都正确地拼写它们)。
同时,您可能想提供一种初始化此类记录的方法。您将要设置默认值,并提供一种轻松填充它的方法。输入右上角的JavaScript构造函数语法:

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


在这里,我们定义了具有一组特定属性的对象。进入这一阶段时,我开始将对象视为具有fields记录。 来自C ++背景,我认为使用function关键字作为定义结构的方法很奇怪,但是在上下文中它实际上是构造函数是有意义的。上面的示例不接受任何参数,但是下面的示例接受可变数量的参数并将其分配给记录字段。

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


该版本接受可变数量的参数。检测到缺少的参数,并将为相应的字段分配默认值。要创建记录的实例,请使用如下语法:

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


构造函数可以做的不仅仅是分配值。它可以基于其他字段计算字段,或者预填充查找表,或者从网页中读取和解析数据,或者从数据库中获取数据-您希望每次实例化时进行的任何类型的初始化记录对象已创建。
更重要的是,记录并不仅仅是存储数据。与任何面向对象的编程一样,您可以提供将应用于关联数据的方法(函数)。例如,我们可以添加:

function PersonRec(p1,p2) {
    this.sNameLast= p1;
    this.sNameFirst=p2;
    ... 
    //-------------------------------- add some methods; i.e., member functions
    this.GetFullName= function() {
       return( this.sNameFirst +" "+ this.sNameLast ); 
    };

    this.toString= function() { 
        var s=  "Name:  " + this.GetFullName() + "\n";
        s+=     "Age:   " + this.nAge          + "\n";
        if ( this.fIsParent ) {
            s+= "Children: "    + this.asChildren;
        }
        return( s );
    };
}


物体。toString()成员已经存在,但仅输出[Object object],这不太有用。编写类似所示的覆盖函数很方便,这样就可以快速显示数据以方便调试。

使用关联数组“记录”

像我们在此处定义的对象这样的对象最常用作此类记录数组中的一项。这是经典的收藏概念。假设有一个选项下拉列表,并且当用户选择一个选项时,我们希望在表单上填充一组输入字段。
您的JavaScript可能会通过使用AJAX,解析网页或从磁盘文件读取来填充集合。或者您可以在源代码中预填充一个数组:

var oCombo= document.getElementById('selectName'); // a <SELECT> element

oCombo.options.length=0;                // clear out the box
oCombo.options.length=arPersons.length; // prepare to repopulate

for (var j=0; j<arPersons.length; j++) {
   oCombo.options[j].text= arPersons[j].sNameLast;
}

... later, see what's been selected ...

var i= oCombo.selectedIndex;
alert( arPersons[i].sNameFirst +" is "+ arPersons[i].nAge );


现在我们已经定义了这些记录的数组,我们可以使用JavaScript数组语法轻松地遍历它们:

var oCombo= document.getElementById('selectName'); // a <SELECT> element

oCombo.options.length=0;                // clear out the box
oCombo.options.length=arPersons.length; // prepare to repopulate

for (var j=0; j<arPersons.length; j++) {
   oCombo.options[j].text= arPersons[j].sNameLast;
}

... later, see what's been selected ...

var i= oCombo.selectedIndex;
alert( arPersons[i].sNameFirst +" is "+ arPersons[i].nAge );


并生成一个像这样的表:

...只需遍历数组元素并显示PersonRec对象属性值,如下所示:

function BuildOutputTable() {
    var sOut="<table border=2>";
    sOut +="<tr>";
    sOut +="<td>Last Name</td><td>First Name</td><td>Age</td><td># of Kids</td>"
    sOut +="</tr>";
    for ( var j=0; j<arPersons.length; j++ ) {
        var rP= arPersons[j];  // a PersonRec object
        sOut += "<tr>";
        sOut += "<td>" +rP.sNameLast+         "</td>";
        sOut += "<td>" +rP.sNameFirst+        "</td>";
        sOut += "<td>" +rP.nAge+              "</td>";
        sOut += "<td>" +rP.asChildren.length+ "</td>";
        sOut += "</tr>";
    }
    sOut += "</table>";
    return(sOut);
}

Tags:

最近发表
标签列表