5.5 使用变量及类型
在前面的例子中你看到了如何定义变量:你用var关键字,然后可选地在语句中为变量赋值。在函数中定义的变量是本地变量,适合仅在函数内使用。直接定义在script元素中的变量是全局变量,可在任意位置访问,包括同一HTML文档中的其他脚本。清单5-8演示了本地和全局变量的使用。
清单5-8 在文件jsdemo.html中使用本地和全局变量
JavaScript是动态类型语言。这并不说明JavaScript没有类型。它只是说你并非一定要显式声明变量类型,你可以轻而易举地为同一变量赋值不同类型。JavaScript会根据你为变量赋的值确定其类型,然后根据它们使用时的上下文在类型间自由转换。清单5-8的结果如下:
在AngularJS开发中使用全局变量是不被赞成的,因为它其实破坏了关注点的分离(我在第3章讲过的),并使其执行单元测试更困难(我在第25章中讲述)。一般来说,如果你必须使用全局变量让两个组件交流,那说明应用程序的设计已经错了。
5.5.1 使用基本类型
JavaScript定义了一组基本类型:string(字符串)、number(数字)和boolean(布尔)。这可能看起来像个简表(short list),但JavaScript设法为这三个类型做了很大的灵活性。
1.使用布尔
布尔类型有两个值:true和false。清单5-9列出了二者的使用,但该类型是条件语句中最常用的,比如if语句。该清单没有控制台输出。
清单5-9 在文件jsdemo.html中定义布尔值
2.使用字符串
你可以使用双引号或单引号定义字符串,如清单5-10所示。
清单5-10 在文件jsdemo.html中定义字符串变量
你使用的引号必须匹配。举个例子,你不能用单引号开始一个字符串又用双引号结束。该清单没有控制台输出。AngularJS包含三个工具方法可以让字符串的使用更容易些,如表5-2中所述。
表5-2 处理字符串的AngularJS方法
你可以在清单5-11看到全部三个与字符串相关的AngularJS的方法。
清单5-11 在文件jsdemo.html中使用AngularJS与字符串相关的方法
方法angular.isString用于当你处理不确定类型的对象时。这是AngularJS为键入的对象提供的若干方法之一,本章会常常讲到。方法angular.uppercase和angular.lowercase做的也许正如你所想象的,清单中的语句在控制台中产生如下输出:
3.使用数字
数字类型常用于代表整数(integer)和浮点数(floating-point)的数字(也称为实数)。清单5-12以供演示。
清单5-12 在jsdemo.html文件中定义数字值
你无需指定你所用数字的类型。你只需表示你需要的值,然后JavaScript会顺势而为。在清单中,我定义了整数,定义了浮点数,以及以0x为前缀的值用来表示十六进制数值。
AngularJS为标准JavaScript功能补充了angular.isNumber方法,传给它对象或值,如果是数字则返回true,否则返回false。该示例在控制台中产生了以下输出:
5.5.2 创建对象
有不同的方式创建JavaScript对象。清单5-13给出了简单示例。
提示:
JavaScript提供了对原型继承的支持,它允许新对象去继承功能。这并没在JavaScript中广泛使用,但我会在第18章中简单介绍,因为它是支持AngularJS服务被创建的方式之一。
清单5-13 在文件jsdemo.html中创建对象
我调用new Object()创建了对象,并将结果(刚创建的对象)赋给了变量myData。一旦对象被创建,我仅通过赋值就可以在该对象上定义属性,像这样:
在该语句之前,我的对象没有属性name。在该语句被执行后,属性存在了,它被赋值了“Adam”。你可以用句点1连接变量名和属性名来读取属性的值,像这样:
清单结果如下:
1.使用对象字面量
你可以使用对象字面量格式一步到位地定义对象及其属性。清单5-14显示了这是如何做的。
清单5-14 在文件jsdemo.html中使用对象字面量格式
每个你想定义的属性都用冒号(:)与其值隔开,属性间用逗号(,)隔开。这和前面的例子有相同效果,清单结果如下:
2.使用函数作为方法
我最喜爱的JavaScript特性之一就是你可以为对象添加函数的方式。被定义在对象上的函数叫方法(method)。清单5-15显示你可以如何以此种方式添加方法。
清单5-15 在文件jsdemo.html文件中为对象添加方法
在本例中,我使用了函数创建方法printMessage。注意参考由对象定义的属性,我必须使用this关键字。当函数用来作为方法时,被调用的方法所依附的对象就暗中通过特殊变量this作为参数传入了函数。清单输出如下:
3.扩展对象
AngularJS通过angular.extend方法,使从一个对象往另一个对象复制方法和属性变得容易,在清单5-16中我演示了它。
清单5-16 在文件jsdemo.html中扩展对象
在本例中我创建了带有city属性的对象,并将它赋值给了变量myExtendedObject。然后我使用angular.extend方法从myData对象上复制所有的属性和函数到myExtendedObject上去。最后,演示原有和复制属性的混合,我使用console.log方法写出name和city属性的值,控制台产生的输出如下:
提示:
方法extend保存目标对象上的所有属性和方法。如果你想无保留地创建对象的副本,那你可以使用angular.copy方法代替。
5.5.3 使用对象
一旦你创建了对象,你就可以用它们做一些事。在下面的段落中,我会讲在本书后面都会用到的活动。
1.检查对象
AngularJS提供angular.isObject方法,如果随之被调用的参数是对象则返回true,否则返回false,如清单5-17所演示的。
清单5-17 在文件jsdemo.html中检查对象
我定义了对象、字符串和数字,并全都使用angular.isObject方法判定它们,在控制台产生了如下输出:
2.读取和修改属性的值
最显而易见的要用对象做的事是,读取或修改赋给对象所定义属性的值。有两种你可以使用的不同语法风格,二者皆在清单5-18中所示。
清单5-18 在文件jsdemo.html中读取和修改对象属性
第一种风格是众多程序员所熟悉的,我在前面示例中用到过。你用句点把对象名称和属性名称连在一起,像这样:
你可以使用等号(=)为属性赋一个新值,或忽略它而读取当前值。第二种风格就是数组风格的索引,像这样:
在这种风格中,你在方括号(“[”和“]”)之间指定你要的属性名称。它可能是个方便的存取属性的方式,因为你可以把你感兴趣的属性名作为变量传入,像这样:
这是你如何枚举对象属性的基础,我一会儿讲它。这里是清单在控制台的输出。
3.枚举对象的属性
枚举对象的属性要使用for...in语句。清单5-19显示了你可以如何使用该语句。
清单5-19 在文件jsdemo.html中枚举对象的属性
循环for...in是标准的JavaScript特性,为myData对象中的每个属性执行代码块中的语句。变量prop被赋值为每个迭代中所处理的属性名称。我使用数组索引风格从对象中取回属性的值。
AngularJS提供的angular.forEach方法是另一个选择,它要的是一个对象和一个将为其每个属性执行的函数。通过value和key参数将当前属性值及其名称传给函数。效果和使用for...in循环一样,正如以下控制台输出所示:
从结果中,你可以看到我在myData对象上作为方法而定义的函数同时以两种情况枚举。这正是JavaScript处理函数的灵活方式所致,但在你刚接触JavaScript时有些事还是需要注意的。
4.添加和删除属性和方法
即使你已经使用对象字面量风格定义了新属性,你仍然可以在对象上定义它。清单5-20做出了演示(本段清单未产生任何控制台输出)。
清单5-20 在文件jsdemo.html中为对象添加新属性
在该清单中,我为对象dayOfWeek添加了新属性。我使用了点标记(用句点把对象和属性的名称连接起来),但我也能轻易地使用索引风格标记。正如你现在可能期望的,你也可以通过将属性的值设为函数为对象添加新方法,如清单5-21所示。
清单5-21 在文件jsdemo.html中为对象添加新方法
你可以使用delete关键字从对象上删除属性或方法,如清单5-22所示。
清单5-22 在文件jsdemo.html中从对象上删除属性
5.判断对象是否拥有属性
你可以使用in表达式查看对象是否拥有某属性,如清单5-23所示。
清单5-23 在文件jsdemo.html中查看对象是否拥有某属性
在本例中,我测试了存在和不存在的属性。变量hasName的值是true,变量hasData的值是false,如下: