JavaScript 对象

对象则用来存储键值对和更复杂的实体。在 JavaScript 中,对象几乎渗透到了这门编程语言的方方面面。所以,在我们深入理解这门语言之前,必须先理解对象。

1 . 创建对象方法

我们可以通过使用带有可选 属性列表 的花括号 {…} 来创建对象。一个属性就是一个键值对(“key: value”),其中键(key)是一个字符串(也叫做属性名),值(value)可以是任何值。

我们可以把对象想象成一个带有签名文件的文件柜。每一条数据都基于键(key)存储在文件中。这样我们就可以很容易根据文件名(也就是“键”)查找文件或添加/删除文件了。

我们可以用下面两种语法中的任一种来创建一个空的对象(“空柜子”):


let user = new Object(); // “构造函数” 的语法
let user = {};  // “字面量” 的语法

通常,我们用花括号。这种方式我们叫做 字面量

2. 对象文本和属性

我们可以在创建对象的时候,立即将一些属性以键值对的形式放到 {...} 中。

let user = {     // 一个对象
  name: "John",  // 键 "name",值 "John"
  age: 30        // 键 "age",值 30
};

属性有键(或者也可以叫做“名字”或“标识符”),位于冒号 ":" 的前面,值在冒号的右边。

在 user 对象中,有两个属性:

  1. 第一个的键是 "name",值是 "John"
  2. 第二个的键是 "age",值是 30

生成的 user 对象可以被想象为一个放置着两个标记有 “name” 和 “age” 的文件的柜子。

我们可以随时添加、删除和读取文件。

可以使用点符号访问属性值:

// 读取文件的属性:
alert( user.name ); // John
alert( user.age ); // 30

属性的值可以是任意类型,让我们加个布尔类型:

user.isAdmin = true;

我们可以用 delete 操作符移除属性:

delete user.age;

我们也可以用多字词语来作为属性名,但必须给它们加上引号:

let user = {
  name: "John",
  age: 30,
  "likes birds": true  // 多词属性名必须加引号
};

列表中的最后一个属性应以逗号结尾:

let user = {
  name: "John",
  age: 30,
}

这叫做尾随(trailing)或悬挂(hanging)逗号。这样便于我们添加、删除和移动属性,因为所有的行都是相似的。

3. 对象使用方括号

对于多词属性,点操作就不能用了:

// 这将提示有语法错误
user.likes birds = true

JavaScript 理解不了。它认为我们在处理 user.likes,然后在遇到意外的 birds 时给出了语法错误。

点符号要求 key 是有效的变量标识符。这意味着:不包含空格,不以数字开头,也不包含特殊字符(允许使用 $ 和 _)。

有另一种方法,就是使用方括号,可用于任何字符串:

let user = {};
// 设置
user["likes birds"] = true;

// 读取
alert(user["likes birds"]); // true

// 删除
delete user["likes birds"];

现在一切都可行了。请注意方括号中的字符串要放在引号中,单引号或双引号都可以。

方括号同样提供了一种可以通过任意表达式来获取属性名的方式 —— 与文本字符串不同 —— 例如下面的变量:

let key = "likes birds";

// 跟 user["likes birds"] = true; 一样
user[key] = true;

在这里,变量 key 可以是程序运行时计算得到的,也可以是根据用户的输入得到的。然后我们可以用它来访问属性。这给了我们很大的灵活性。

例如:

let user = {
  name: "John",
  age: 30
};

let key = prompt("What do you want to know about the user?", "name");

// 访问变量
alert( user[key] ); // John(如果输入 "name")

点符号不能以类似的方式使用:

let user = {
  name: "John",
  age: 30
};

let key = "name";
alert( user.key ) // undefined

4. 属性值简写

在实际开发中,我们通常用已存在的变量当做属性名。

function makeUser(name, age) {
  return {
    name: name,
    age: age,
    // ……其他的属性
  };
}

let user = makeUser("John", 30);
alert(user.name); // John

在上面的例子中,属性名跟变量名一样。这种通过变量生成属性的应用场景很常见,在这有一种特殊的 属性值缩写 方法,使属性名变得更短。

可以用 name 来代替 name:name 像下面那样

function makeUser(name, age) {
  return {
    name, // 与 name: name 相同
    age,  // 与 age: age 相同
    // ...
  };
}

我们可以把属性名简写方式和正常方式混用:

let user = {
  name,  // 与 name:name 相同
  age: 30
};

5. 对象属性名称限制

变量名不能是编程语言的某个保留字,如 “for”、“let”、“return” 等……

但对象的属性名并不受此限制:

// 这些属性都没问题
let obj = {
  for: 1,
  let: 2,
  return: 3
};

alert( obj.for + obj.let + obj.return );  // 6

,属性命名没有限制。属性名可以是任何字符串或者 symbol(一种特殊的标志符类型,将在后面介绍)。

其他类型会被自动地转换为字符串。

例如,当数字 0 被用作对象的属性的键时,会被转换为字符串 "0"

let obj = {
  0: "test" // 等同于 "0": "test"
};

// 都会输出相同的属性(数字 0 被转为字符串 "0")
alert( obj["0"] ); // test
alert( obj[0] ); // test (相同的属性)

这里有个小陷阱:一个名为 __proto__ 的属性。我们不能将它设置为一个非对象的值:

let obj = {};
obj.__proto__ = 5; // 分配一个数字
alert(obj.__proto__); // [object Object] —— 值为对象,与预期结果不同

6. 对象属性存在性测试,“in” 操作符

比于其他语言,JavaScript 的对象有一个需要注意的特性:能够被访问任何属性。即使属性不存在也不会报错!

读取不存在的属性只会得到 undefined。所以我们可以很容易地判断一个属性是否存在:

let user = {};

alert( user.noSuchProperty === undefined ); // true 意思是没有这个属性

这里还有一个特别的,检查属性是否存在的操作符 "in"

语法是:

"key" in object

例如:

let user = { name: "John", age: 30 };

alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。

7. 对象中使用”for..in” 循环

为了遍历一个对象的所有键(key),可以使用一个特殊形式的循环:for..in。这跟我们在前面学到的 for(;;) 循环是完全不一样的东西。

语法:

for (key in object) {
  // 对此对象属性中的每个键执行的代码
}

例如,让我们列出 user 所有的属性:

et user = {
  name: "John",
  age: 30,
  isAdmin: true
};

for (let key in user) {
  // keys
  alert( key );  // name, age, isAdmin
  // 属性键的值
  alert( user[key] ); // John, 30, true
}

注意,所有的 “for” 结构体都允许我们在循环中定义变量,像这里的 let key

同样,我们可以用其他属性名来替代 key。例如 "for(let prop in obj)" 也很常用。

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注