6.1 Object
到目前为止,大多数引用值的示例使用的是Object类型。Object是ECMAScript中最常用的类型之一。虽然Object的实例没有多少功能,但很适合存储和在应用程序间交换数据。
显式地创建Object的实例有两种方式。第一种是使用new操作符和Object构造函数,如下所示:
let person = new Object(); person.name = "Nicholas"; person.age = 29;
另一种方式是使用对象字面量(object literal)表示法。对象字面量是对象定义的简写形式,目的是为了简化包含大量属性的对象的创建。比如,下面的代码定义了与前面示例相同的person对象,但使用的是对象字面量表示法:
let person = { name: "Nicholas", age: 29 };
在这个例子中,左大括号({)表示对象字面量开始,因为它出现在一个表达式上下文(expression context)中。在ECMAScript中,表达式上下文指的是期待返回值的上下文。赋值操作符表示后面要期待一个值,因此左大括号表示一个表达式的开始。同样是左大括号,如果出现在语句上下文(statement context)中,比如if语句的条件后面,则表示一个语句块的开始。
接下来指定了name属性,后跟一个冒号,然后是属性的值。逗号用于在对象字面量中分隔属性,因此字符串"Nicholas"后面有一个逗号,而29后面没有,因为age是这个对象的最后一个属性。在最后一个属性后面加上逗号在非常老的浏览器中会导致报错,但所有现代浏览器都支持这种写法。
在对象字面量表示法中,属性名可以是字符串或数值,比如:
let person = { "name": "Nicholas", "age": 29, 5: true };
这个例子会得到一个带有属性name、age和5的对象。注意,数值属性会自动转换为字符串。
当然也可以用对象字面量表示法来定义一个只有默认属性和方法的对象,只要使用一对大括号,中间留空就行了:
letperson={};//与newObject()相同 person.name = "Nicholas"; person.age = 29;
这个例子跟本节开始的第一个例子是等效的,虽然看起来有点怪。对象字面量表示法通常只在为了让属性一目了然时才使用。
注意 在使用对象字面量表示法定义对象时,并不会实际调用Object构造函数。
虽然使用哪种方式创建Object实例都可以,但实际上开发者更倾向于使用对象字面量表示法。这是因为对象字面量代码更少,看起来也更有封装所有相关数据的感觉。事实上,对象字面量已经成为给函数传递大量可选参数的主要方式,比如:
function displayInfo(args) { let output = ""; if (typeof args.name == "string"){ output += "Name: " + args.name + "\n"; } if (typeof args.age == "number") { output += "Age: " + args.age + "\n"; } alert(output); } displayInfo({ name: "Nicholas", age: 29 }); displayInfo({ name: "Greg" });
这里,函数displayInfo()接收一个名为args的参数。这个参数可能有属性name或age,也可能两个属性都有或者都没有。函数内部会使用typeof操作符测试每个属性是否存在,然后根据属性有无构造并显示一条消息。然后,这个函数被调用了两次,每次都通过一个对象字面量传入了不同的数据。两种情况下,函数都正常运行。
注意 这种模式非常适合函数有大量可选参数的情况。一般来说,命名参数更直观,但在可选参数过多的时候就显得笨拙了。最好的方式是对必选参数使用命名参数,再通过一个对象字面量来封装多个可选参数。
虽然属性一般是通过点语法来存取的,这也是面向对象语言的惯例,但也可以使用中括号来存取属性。在使用中括号时,要在括号内使用属性名的字符串形式,比如:
console.log(person["name"]); // "Nicholas" console.log(person.name); // "Nicholas"
从功能上讲,这两种存取属性的方式没有区别。使用中括号的主要优势就是可以通过变量访问属性,就像下面这个例子中一样:
let propertyName = "name"; console.log(person[propertyName]); // "Nicholas"
另外,如果属性名中包含可能会导致语法错误的字符,或者包含关键字/保留字时,也可以使用中括号语法。比如:
person["first name"] = "Nicholas";
因为"first name"中包含一个空格,所以不能使用点语法来访问。不过,属性名中是可以包含非字母数字字符的,这时候只要用中括号语法存取它们就行了。
通常,点语法是首选的属性存取方式,除非访问属性时必须使用变量。
注意 第8章将更全面、深入地介绍Object类型。