Skip to content

1.3 对象与数组

对象和数组是 JavaScript 中最重要的数据结构,用于存储和组织数据。

一、对象(Object)

1. 创建对象

javascript
// 对象字面量
const person = {
    name: "张三",
    age: 25,
    city: "北京",
    greet: function() {
        console.log("Hello!");
    }
};

// new Object()
const person2 = new Object();
person2.name = "李四";
person2.age = 30;

// 工厂函数
function createPerson(name, age) {
    return {
        name,
        age,
        greet() {
            console.log(`Hello, I'm ${this.name}`);
        }
    };
}

const person3 = createPerson("王五", 28);

// 构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.greet = function() {
        console.log(`Hello, I'm ${this.name}`);
    };
}

const person4 = new Person("赵六", 27);

2. 访问属性

javascript
const person = {
    name: "张三",
    age: 25,
    "full name": "张三丰"
};

// 点表示法
console.log(person.name);        // "张三"

// 方括号表示法
console.log(person["age"]);      // 25
console.log(person["full name"]);// "张三丰"(必须用于特殊属性名)

// 动态属性名
const key = "name";
console.log(person[key]);        // "张三"

3. 添加/修改/删除属性

javascript
const person = { name: "张三" };

// 添加属性
person.age = 25;
person.city = "北京";

// 修改属性
person.name = "李四";

// 删除属性
delete person.city;

// Object.defineProperty(定义属性)
const obj = {};
Object.defineProperty(obj, "name", {
    value: "张三",
    writable: true,   // 可写
    enumerable: true, // 可遍历
    configurable: true, // 可删除
    get() {
        return "张三";
    },
    set(value) {
        // 设置逻辑
    }
});

4. 对象方法

javascript
const person = {
    name: "张三",
    age: 25,

    greet() {
        console.log(`Hello, I'm ${this.name}`);
    },

    sayHello: function() {
        console.log(`Hello!`);
    }
};

person.greet();     // 调用方法
person["greet"](); // 另一种方式

5. 遍历对象

javascript
const person = { name: "张三", age: 25, city: "北京" };

// for...in
for (let key in person) {
    console.log(key, person[key]);
}

// Object.keys()
console.log(Object.keys(person)); // ["name", "age", "city"]

// Object.values()
console.log(Object.values(person)); // ["张三", 25, "北京"]

// Object.entries()
console.log(Object.entries(person)); // [["name", "张三"], ["age", 25], ["city", "北京"]]

// Object.fromEntries()
const entries = [["name", "张三"], ["age", 25]];
console.log(Object.fromEntries(entries)); // { name: "张三", age: 25 }

6. 对象解构

javascript
const person = { name: "张三", age: 25, city: "北京" };

// 基本解构
const { name, age } = person;

// 重命名
const { name: userName, age: userAge } = person;

// 默认值
const { name, country = "中国" } = person;

// 嵌套解构
const user = {
    name: "张三",
    address: {
        city: "北京",
        street: "长安街"
    }
};

const {
    address: { city }
} = user;

// 解构剩余属性
const { name: userName, ...rest } = person;
console.log(rest); // { age: 25, city: "北京" }

7. 对象展开

javascript
const person = { name: "张三", age: 25 };

// 合并对象
const newPerson = { ...person, city: "北京" };
console.log(newPerson); // { name: "张三", age: 25, city: "北京" }

// 修改属性
const updatedPerson = { ...person, age: 26 };
console.log(updatedPerson); // { name: "张三", age: 26 }

// Object.assign
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = Object.assign({}, obj1, obj2);
console.log(merged); // { a: 1, b: 2 }

二、数组(Array)

1. 创建数组

javascript
// 数组字面量
const arr1 = [1, 2, 3];
const arr2 = ["张三", "李四", "王五"];
const arr3 = [1, "hello", true, { name: "张三" }];

// Array 构造函数
const arr4 = new Array(1, 2, 3);
const arr5 = new Array(5); // 创建 5 个空元素

// Array.from
const arr6 = Array.from("hello");
console.log(arr6); // ["h", "e", "l", "l", "o"]

// Array.of
const arr7 = Array.of(1, 2, 3);

2. 访问元素

javascript
const arr = ["张三", "李四", "王五", "赵六"];

// 下标访问(从 0 开始)
console.log(arr[0]); // "张三"
console.log(arr[1]); // "李四"

// at()(负索引)
console.log(arr.at(-1)); // "赵六"
console.log(arr.at(-2)); // "王五"

// length 属性
console.log(arr.length); // 4

3. 添加/删除元素

javascript
const arr = ["张三", "李四"];

// push(末尾添加)
arr.push("王五");        // arr: ["张三", "李四", "王五"]

// pop(末尾删除)
arr.pop();              // arr: ["张三", "李四"]

// unshift(头部添加)
arr.unshift("王五");     // arr: ["王五", "张三", "李四"]

// shift(头部删除)
arr.shift();            // arr: ["张三", "李四"]

// splice(任意位置添加/删除)
arr.splice(1, 0, "王五"); // 在索引 1 添加,返回空数组
arr.splice(1, 1);         // 删除索引 1 的元素,返回 ["王五"]
arr.splice(0, 2, "新增"); // 删除 2 个,添加 1 个

4. 查找元素

javascript
const arr = [
    { id: 1, name: "张三" },
    { id: 2, name: "李四" },
    { id: 3, name: "王五" }
];

// indexOf(查找下标)
const index = arr.indexOf("张三"); // 0

// includes(是否存在)
const exists = arr.includes("张三"); // true

// find(查找元素)
const found = arr.find(item => item.id === 2);
console.log(found); // { id: 2, name: "李四" }

// findIndex(查找下标)
const foundIndex = arr.findIndex(item => item.id === 2);
console.log(foundIndex); // 1

5. 遍历数组

javascript
const arr = [1, 2, 3, 4, 5];

// forEach
arr.forEach((item, index) => {
    console.log(index, item);
});

// for...of
for (const item of arr) {
    console.log(item);
}

// for...in(不推荐)
for (const index in arr) {
    console.log(index, arr[index]);
}

// map
const doubled = arr.map(item => item * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// filter
const evens = arr.filter(item => item % 2 === 0);
console.log(evens); // [2, 4]

// reduce
const sum = arr.reduce((total, item) => total + item, 0);
console.log(sum); // 15

// some(是否有一个满足)
const hasEven = arr.some(item => item % 2 === 0);
console.log(hasEven); // true

// every(是否都满足)
const allPositive = arr.every(item => item > 0);
console.log(allPositive); // true

6. 数组解构

javascript
const arr = ["张三", "李四", "王五", "赵六"];

// 基本解构
const [first, second] = arr;

// 跳过元素
const [, , third] = arr; // "王五"

// 剩余元素
const [first, ...rest] = arr;
console.log(rest); // ["李四", "王五", "赵六"]

// 默认值
const [a, b, c, d, e = "默认值"] = arr;
console.log(e); // "赵六"

// 交换变量
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x, y); // 2, 1

7. 数组其他方法

javascript
const arr = [3, 1, 4, 1, 5, 9, 2, 6];

// sort(排序)
arr.sort(); // [1, 1, 2, 3, 4, 5, 6, 9]
arr.sort((a, b) => a - b); // 数字排序(升序)
arr.sort((a, b) => b - a); // 数字排序(降序)

// reverse(反转)
arr.reverse();

// concat(合并)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]

// slice(切片)
const arr = [1, 2, 3, 4, 5];
const sliced = arr.slice(1, 3); // [2, 3]

// join(转字符串)
const arr = ["张三", "李四", "王五"];
const str = arr.join(", "); // "张三, 李四, 王五"

// toString
console.log(arr.toString()); // "张三,李四,王五"

// flat(扁平化)
const nested = [1, [2, [3, [4]]]];
const flat = nested.flat(2); // [1, 2, 3, [4]]
const completelyFlat = nested.flat(Infinity); // [1, 2, 3, 4]

// isArray
console.log(Array.isArray([1, 2, 3])); // true

三、对象与数组常用技巧

1. 深拷贝

javascript
// JSON 方法(简单但有限制)
const original = { name: "张三", age: 25 };
const copy = JSON.parse(JSON.stringify(original));

// 结构化克隆(现代浏览器)
const copy2 = structuredClone(original);

// Lodash
// const copy3 = _.cloneDeep(original);

2. 冻结对象

javascript
const obj = { name: "张三", age: 25 };

Object.freeze(obj);
obj.age = 30; // 不生效(严格模式下报错)

// 判断
console.log(Object.isFrozen(obj)); // true

3. 数组去重

javascript
// Set
const arr = [1, 2, 2, 3, 3, 3];
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3]

// filter + indexOf
const unique2 = arr.filter((item, index) => arr.indexOf(item) === index);

4. 数组转对象

javascript
const arr = [
    ["name", "张三"],
    ["age", 25]
];

const obj = Object.fromEntries(arr);
console.log(obj); // { name: "张三", age: 25 }

四、总结

  • 对象用于存储键值对数据
  • 数组用于存储有序数据
  • 解构和展开让代码更简洁
  • 熟练掌握常用方法能提高开发效率