JavaScript 对象与数组

对象

一、对象基础概念

对象是 JavaScript 的核心数据类型,用于存储键值对集合。可以理解为现实事物的代码映射。
// 一个简单的用户对象 let user = { name: "张三", // 属性:键值对 age: 25, "full name": "张三丰", // 包含空格的属性名需要引号 sayHi: function() { // 方法:值为函数的属性 return "你好"; } };
  1. 使用对象字面量创建对象,避免 new Object()
  2. 属性名使用驼峰命名,除非必要不使用引号
  3. 使用解构赋值提高代码可读性
  4. 注意区分浅拷贝和深拷贝
  5. 使用 Object.freeze() 保护配置对象
  6. 遍历对象优先使用 Object.keys() 和 for...of

二、创建对象

1. 对象字面量(最常用)

字面量语法是创建对象最直接的方式,它允许我们在大括号`{}`中直接定义对象的属性和方法。

const person = { name: "李四", age: 30, job: "工程师" };
2. 使用 new Object()

这种方式在某些特定场景下可能更为适用,例如在需要动态创建对象并根据条件设置属性时。

const person = new Object(); person.name = "王五"; person.age = 28;
3. 使用构造函数
function Person(name, age) { this.name = name; this.age = age; this.greet = function() { return `你好,我是${this.name}`; }; } const p1 = new Person("赵六", 22);
4. 使用 Object.create()
const proto = { greet() { return "你好"; } }; const obj = Object.create(proto); obj.name = "小明";
5. 使用类(ES6+)
class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { return `你好,我是${this.name}`; } }

三、属性的增删改查

1. 访问属性
const user = { name: "小红", age: 20, "my-email": "[email protected]" }; // 点号语法(最常用) console.log(user.name); // "小红" // 方括号语法(特殊属性名、动态属性名时使用) console.log(user["age"]); // 20 console.log(user["my-email"]); // "[email protected]" // 动态属性名 const key = "name"; console.log(user[key]); // "小红" // 可选链操作符(ES2020)- 避免访问不存在的属性时报错 console.log(user?.address?.city); // undefined(不会报错)
2. 添加/修改属性

向对象添加新属性非常简单,只需使用赋值语句即可。如果属性不存在,将会自动创建该属性并赋予相应的值。

const car = {}; // 添加属性 car.brand = "特斯拉"; car["model"] = "Model 3"; car.year = 2023; // 修改属性 car.year = 2024; // 使用变量作为属性名 const propName = "color"; car[propName] = "红色"; console.log(car); // { brand: "特斯拉", model: "Model 3", year: 2024, color: "红色" }
3. 删除属性

使用`delete`运算符可以删除对象的属性。删除后,该属性将不再属于对象,访问时会返回`undefined`。需要注意的是,`delete`操作符仅删除对象自身的属性,如果属性是继承而来,则不会被删除。

const student = { name: "小明", age: 18, score: 95, password: "123456" }; // 删除单个属性 delete student.password; // 删除成功返回 true,属性不存在也返回 true console.log(delete student.age); // true console.log(student); // { name: "小明", score: 95 }

四、属性遍历和检查

1. 检查属性是否存在
const obj = { name: "测试", age: 25 }; // 使用 in 运算符 console.log("name" in obj); // true console.log("job" in obj); // false // 使用 hasOwnProperty(检查自身属性,不包括原型链) console.log(obj.hasOwnProperty("name")); // true console.log(obj.hasOwnProperty("toString")); // false(原型链上的方法) // 直接判断是否为 undefined(不严谨,因为值可能确实是 undefined) console.log(obj.name !== undefined); // true console.log(obj.job !== undefined); // false
2. 遍历对象属性
const person = { name: "张三", age: 30, job: "工程师" }; // 1. for...in 循环(包括原型链上的可枚举属性) for (let key in person) { console.log(key, person[key]); } // 2. Object.keys() - 返回自身属性的键数组 console.log(Object.keys(person)); // ["name", "age", "job"] // 3. Object.values() - 返回自身属性的值数组 console.log(Object.values(person)); // ["张三", 30, "工程师"] // 4. Object.entries() - 返回键值对数组 console.log(Object.entries(person)); // [["name", "张三"], ["age", 30], ["job", "工程师"]] // 5. 遍历 entries Object.entries(person).forEach(([key, value]) => { console.log(`${key}: ${value}`); });

五、对象方法

对象的方法是存储在对象中的函数,用于定义对象的行为。
1. 定义方法

在对象中定义方法时,方法名后跟一个函数表达式。这样,对象就拥有了执行特定任务的能力。通过在对象中封装方法,将数据和操作数据的函数紧密结合在一起,体现了面向对象编程的思想。

let calculator = {     add: function(a, b) {         return a + b;     },     subtract: function(a, b) {         return a - b;     } }; console.log(calculator.add(5, 3)); // 输出 8 console.log(calculator.subtract(5, 3)); // 输出 2

使用箭头函数定义方法

let mathUtils = {     multiply: (a, b) => a * b,     divide: (a, b) => a / b }; console.log(mathUtils.multiply(4, 3)); // 输出 12 console.log(mathUtils.divide(10, 2)); // 输出 5

箭头函数提供了一种更为简洁的方法定义方式。在对象的方法中使用箭头函数时,需要注意`this`的指向问题。箭头函数中的`this`会继承其所在上下文的`this`值,这与传统函数的`this`行为有所不同。因此,在需要正确引用对象自身属性的情况下,需要谨慎使用箭头函数。

2. 常用对象方法
const obj1 = { a: 1, b: 2 }; const obj2 = { c: 3, d: 4 }; // Object.assign() - 合并对象 const merged = Object.assign({}, obj1, obj2); console.log(merged); // { a: 1, b: 2, c: 3, d: 4 } // Object.freeze() - 冻结对象(不能修改、添加、删除) const frozen = Object.freeze({ name: "固定值" }); frozen.name = "新值"; // 严格模式下会报错 console.log(frozen.name); // "固定值"(没变) // Object.seal() - 密封对象(不能添加删除,但可以修改) const sealed = Object.seal({ count: 10 }); sealed.count = 20; // 可以修改 delete sealed.count; // 不能删除 sealed.newProp = "新"; // 不能添加
3. 属性描述符
const user = { name: "张三" }; // 获取属性描述符 const descriptor = Object.getOwnPropertyDescriptor(user, "name"); console.log(descriptor); // { // value: "张三", // writable: true, // 是否可修改 // enumerable: true, // 是否可枚举 // configurable: true // 是否可配置(删除、修改属性特性) // } // 定义属性的元数据 Object.defineProperty(user, "age", { value: 25, writable: false, // 只读 enumerable: false, // 不可枚举 configurable: false // 不可配置 }); console.log(user.age); // 25 user.age = 30; // 修改无效(严格模式报错) console.log(user.age); // 25 console.log(Object.keys(user)); // ["name"](age不可枚举)

六、原型和继承

// 原型链继承 const parent = { greet() { return "你好"; } }; const child = Object.create(parent); child.name = "孩子"; console.log(child.name); // "孩子"(自身属性) console.log(child.greet()); // "你好"(原型上的方法) console.log(child.toString()); // 原型链上的方法 // 获取原型 console.log(Object.getPrototypeOf(child)); // parent对象 // 检查是否是自身属性 console.log(child.hasOwnProperty("name")); // true console.log(child.hasOwnProperty("greet")); // false

七、对象操作

1. 拷贝对象
const original = { a: 1, b: { c: 2 } }; // 浅拷贝 const shallowCopy1 = Object.assign({}, original); const shallowCopy2 = { ...original }; // 深拷贝 const deepCopy = JSON.parse(JSON.stringify(original)); // 注意:这种方法会丢失函数、undefined、Symbol等 // 简单深拷贝函数 function deepClone(obj) { if (obj === null || typeof obj !== "object") return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof Array) return obj.map(item => deepClone(item)); const cloned = {}; Object.keys(obj).forEach(key => { cloned[key] = deepClone(obj[key]); }); return cloned; }
2. 计算属性名
const key = "dynamicKey"; const value = "动态值"; const obj = { [key]: value, // 计算属性名 [`${key}2`]: "另一个值", [1 + 2]: "三" // 属性名可以是表达式 }; console.log(obj); // { dynamicKey: "动态值", dynamicKey2: "另一个值", 3: "三" }
3. 方法简写
const oldStyle = { name: "老方式", sayHi: function() { return "Hi"; } }; const newStyle = { name: "新方式", sayHi() { // 方法简写 return "Hi"; }, // 生成器函数简写 *generator() { yield 1; yield 2; } };

数组

一、数组基础概念

数组是 JavaScript 中用于存储有序集合的特殊对象。可以包含任意类型的元素。

二、创建数组

1. 数组字面量(最常用)
const arr1 = [1, 2, 3, 4, 5]; const arr2 = []; // 空数组 const arr3 = [1, "two", true, null, undefined, { name: "对象" }];
2. 使用 Array 构造函数
const arr1 = new Array(); // [] const arr2 = new Array(5); // [empty × 5] 长度为5的空数组 const arr3 = new Array(1, 2, 3); // [1, 2, 3] // 注意陷阱 const arr4 = new Array(3); // [empty × 3] - 长度为3的空数组 const arr5 = [3]; // [3] - 包含一个元素3的数组
3. 使用 Array.of() (ES6)
const arr1 = Array.of(5); // [5] - 解决了构造函数的歧义 const arr2 = Array.of(1, 2, 3); // [1, 2, 3]
4. 使用 Array.from() (ES6)
// 从类数组对象创建 const str = "hello"; const arr1 = Array.from(str); // ["h", "e", "l", "l", "o"] // 从 Set 创建 const set = new Set([1, 2, 3]); const arr2 = Array.from(set); // [1, 2, 3] // 使用映射函数 const arr3 = Array.from([1, 2, 3], x => x * 2); // [2, 4, 6] // 创建指定范围的数组 const range = Array.from({ length: 5 }, (_, i) => i + 1); // [1, 2, 3, 4, 5]

三、数组的基本操作

1. 访问和修改元素
const arr = ["a", "b", "c", "d"]; // 访问元素 console.log(arr[0]); // "a" - 第一个元素 console.log(arr[arr.length - 1]); // "d" - 最后一个元素 console.log(arr[10]); // undefined - 索引不存在 // 修改元素 arr[1] = "x"; console.log(arr); // ["a", "x", "c", "d"] // 添加元素到任意位置 arr[4] = "e"; console.log(arr); // ["a", "x", "c", "d", "e"] arr[10] = "z"; console.log(arr); // ["a", "x", "c", "d", "e", empty × 5, "z"]
2. length 属性
const arr = [1, 2, 3, 4]; console.log(arr.length); // 4 // 截断数组 arr.length = 2; console.log(arr); // [1, 2] // 清空数组 arr.length = 0; console.log(arr); // [] // 增加长度(会创建空位) arr.length = 5; console.log(arr); // [empty × 5]

四、数组的遍历方法

1. 传统 for 循环
const arr = ["a", "b", "c"]; // 基本for循环 for (let i = 0; i < arr.length; i++) { console.log(arr[i]); } // 反向遍历 for (let i = arr.length - 1; i >= 0; i--) { console.log(arr[i]); }
2. for...of 循环 (ES6)
const arr = ["a", "b", "c"]; for (const item of arr) { console.log(item); } // 同时获取索引和值 for (const [index, value] of arr.entries()) { console.log(index, value); }
3. for...in 循环(不推荐用于数组)
const arr = ["a", "b", "c"]; // 遍历索引(包括自定义属性) for (const index in arr) { console.log(index, arr[index]); }
4. 数组内置遍历方法
const arr = [1, 2, 3, 4, 5]; // forEach - 遍历每个元素 arr.forEach((item, index, array) => { console.log(`索引${index}: ${item}`); }); // 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((acc, item) => acc + 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 // find - 查找第一个满足条件的元素 const found = arr.find(item => item > 3); console.log(found); // 4 // findIndex - 查找第一个满足条件的索引 const foundIndex = arr.findIndex(item => item > 3); console.log(foundIndex); // 3

五、数组的增删改操作

1. 添加元素
const arr = [1, 2, 3]; // push - 末尾添加(返回新长度) arr.push(4, 5); console.log(arr); // [1, 2, 3, 4, 5] // unshift - 开头添加(返回新长度) arr.unshift(-1, 0); console.log(arr); // [-1, 0, 1, 2, 3, 4, 5] // splice - 任意位置添加 arr.splice(3, 0, "a", "b"); // 在索引3处插入"a","b" console.log(arr); // [-1, 0, 1, "a", "b", 2, 3, 4, 5]
2. 删除元素
const arr = [1, 2, 3, 4, 5]; // pop - 删除末尾元素(返回删除的元素) const last = arr.pop(); console.log(last, arr); // 5, [1, 2, 3, 4] // shift - 删除开头元素(返回删除的元素) const first = arr.shift(); console.log(first, arr); // 1, [2, 3, 4] // splice - 删除任意位置元素 const removed = arr.splice(1, 2); // 从索引1开始删除2个 console.log(removed, arr); // [3, 4], [2] // 清空数组的几种方式 let arr2 = [1, 2, 3]; arr2.length = 0; // 方式1 arr2 = []; // 方式2 arr2.splice(0); // 方式3 while(arr2.length) { // 方式4 arr2.pop(); }
3. 修改元素
const arr = [1, 2, 3, 4, 5]; // 直接通过索引修改 arr[2] = 30; // splice - 替换元素 arr.splice(1, 2, 20, 30); // 从索引1开始删除2个,插入20,30 console.log(arr); // [1, 20, 30, 4, 5] // fill - 填充元素(ES6) const filled = new Array(5).fill(0); // [0, 0, 0, 0, 0] arr.fill(9, 1, 3); // 从索引1到3填充9 console.log(arr); // [1, 9, 9, 4, 5]

六、数组的常用方法

1. 合并与切割
const arr1 = [1, 2]; const arr2 = [3, 4]; const arr3 = [5, 6]; // concat - 合并数组(返回新数组) const merged = arr1.concat(arr2, arr3); console.log(merged); // [1, 2, 3, 4, 5, 6] // slice - 切割数组(返回新数组) const sliced = merged.slice(1, 4); // [2, 3, 4] // join - 连接为字符串 const str = merged.join("-"); // "1-2-3-4-5-6" // split - 字符串分割为数组(字符串方法) const arr = "a,b,c".split(","); // ["a", "b", "c"]
2. 查找与判断
const arr = [1, 2, 3, 2, 1]; // indexOf - 查找元素第一次出现的索引 console.log(arr.indexOf(2)); // 1 console.log(arr.indexOf(5)); // -1 // lastIndexOf - 查找元素最后一次出现的索引 console.log(arr.lastIndexOf(2)); // 3 // includes - 是否包含元素(ES6) console.log(arr.includes(3)); // true console.log(arr.includes(5)); // false // find - 查找满足条件的第一个元素 const found = arr.find(item => item > 2); // 3 // findIndex - 查找满足条件的第一个索引 const foundIndex = arr.findIndex(item => item > 2); // 2
3. 排序与反转
const arr = [3, 1, 4, 1, 5, 9, 2, 6]; // sort - 排序(修改原数组) arr.sort(); console.log(arr); // [1, 1, 2, 3, 4, 5, 6, 9](默认按字符串排序) // 自定义排序 const numbers = [3, 1, 4, 1, 5, 9]; numbers.sort((a, b) => a - b); // 升序 console.log(numbers); // [1, 1, 3, 4, 5, 9] numbers.sort((a, b) => b - a); // 降序 console.log(numbers); // [9, 5, 4, 3, 1, 1] // reverse - 反转数组 const arr2 = [1, 2, 3, 4]; arr2.reverse(); console.log(arr2); // [4, 3, 2, 1]
4. 数组转换
const arr = [1, 2, 3, 4, 5]; // map - 映射 const doubled = arr.map(x => x * 2); // filter - 过滤 const evens = arr.filter(x => x % 2 === 0); // reduce - 归约 const sum = arr.reduce((acc, x) => acc + x, 0); // flat - 扁平化数组(ES2019) const nested = [1, [2, 3], [4, [5, 6]]]; const flat1 = nested.flat(); // [1, 2, 3, 4, [5, 6]] const flat2 = nested.flat(2); // [1, 2, 3, 4, 5, 6] // flatMap - 映射后扁平化 const result = [1, 2, 3].flatMap(x => [x, x * 2]); console.log(result); // [1, 2, 2, 4, 3, 6]

七、多维数组

// 创建二维数组 const matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; // 访问元素 console.log(matrix[1][2]); // 6 // 遍历二维数组 for (let i = 0; i < matrix.length; i++) { for (let j = 0; j < matrix[i].length; j++) { console.log(`matrix[${i}][${j}] = ${matrix[i][j]}`); } } // 创建指定大小的二维数组 function createMatrix(rows, cols, initial = 0) { return Array.from({ length: rows }, () => Array.from({ length: cols }, () => initial) ); } const matrix2 = createMatrix(3, 3, 0); console.log(matrix2); // [[0,0,0], [0,0,0], [0,0,0]]

八、数组的高级技巧

1. 数组去重
const arr = [1, 2, 2, 3, 3, 3, 4, 4, 5]; // 使用 Set const unique1 = [...new Set(arr)]; console.log(unique1); // [1, 2, 3, 4, 5] // 使用 filter 和 indexOf const unique2 = arr.filter((item, index) => arr.indexOf(item) === index); // 使用 reduce const unique3 = arr.reduce((acc, item) => { if (!acc.includes(item)) acc.push(item); return acc; }, []);
2. 数组交集、并集、差集
const arr1 = [1, 2, 3, 4]; const arr2 = [3, 4, 5, 6]; // 并集 const union = [...new Set([...arr1, ...arr2])]; console.log(union); // [1, 2, 3, 4, 5, 6] // 交集 const intersection = arr1.filter(item => arr2.includes(item)); console.log(intersection); // [3, 4] // 差集(arr1中有但arr2中没有) const difference = arr1.filter(item => !arr2.includes(item)); console.log(difference); // [1, 2]
3. 数组分组
const arr = [ { name: "张三", age: 25, department: "技术部" }, { name: "李四", age: 30, department: "市场部" }, { name: "王五", age: 28, department: "技术部" }, { name: "赵六", age: 35, department: "市场部" } ]; // 按部门分组 const grouped = arr.reduce((acc, person) => { const dept = person.department; if (!acc[dept]) { acc[dept] = []; } acc[dept].push(person); return acc; }, {}); console.log(grouped); // { // 技术部: [{ name: "张三", ... }, { name: "王五", ... }], // 市场部: [{ name: "李四", ... }, { name: "赵六", ... }] // }
4. 数组打平与链式调用
const data = [ { category: "水果", items: ["苹果", "香蕉"] }, { category: "蔬菜", items: ["白菜", "萝卜"] } ]; // 获取所有物品 const allItems = data .flatMap(category => category.items) .map(item => item.toUpperCase()) .filter(item => item.length > 2) .sort(); console.log(allItems); // ["苹果", "香蕉", "白菜", "萝卜"](按拼音排序)

九、类数组对象

// 常见的类数组对象 function example() { console.log(arguments); // 类数组对象 console.log(Array.isArray(arguments)); // false // 转换为真实数组 const args1 = Array.from(arguments); const args2 = [...arguments]; const args3 = Array.prototype.slice.call(arguments); } example(1, 2, 3); // DOM 元素集合 const divs = document.querySelectorAll('div'); const divArray = Array.from(divs); // 转换为数组

Read more

【AI】——结合Ollama、Open WebUI和Docker本地部署可视化AI大语言模型

【AI】——结合Ollama、Open WebUI和Docker本地部署可视化AI大语言模型

🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大三学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL,Javaweb,Rust,python】 🎈热门专栏:🎊【Springboot,Redis,Springsecurity,Docker,AI】  感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️ 目录 🎈本地部署模型 🎉安装Ollama 🎉安装 Open WebUI 🎊安装Docker 🥞启动 Hyper-v 🥞 安装 WSL(适用于Linux的Windows的子系统): 🥞安装Docker  🎊Docker 部署 Open WebUI 🎈本地部署模型 🎉安装Ollama 官网: Ollama 然后进行一下下载 安装完成之后是没有提示的,然后我们需要去测试一下。(这里我是以QWen为例子,大家可以尝试其他的模型) 打开一个终端,

By Ne0inhk

仓库管理系统-17-前端之物品类型管理

文章目录 * 1 表设计(goodstype) * 2 后端代码 * 2.1 Goodstype.java * 2.2 GoodstypeMapper.java * 2.3 GoodstypeService.java * 2.4 GoodstypeServiceImpl.java * 2.5 GoodstypeController.java * 3 前端代码 * 3.1 goodstype/GoodstypeManage.vue * 3.2 添加菜单 * 3.3 页面显示 1、goodstype表设计。2、根据表生成后端代码。3、编写后端增删改查代码。4、ApiPost测试查询代码。5、编写前端相关代码。 1

By Ne0inhk

前端常用字符串/数组操作(含相关手撕)

字符串转数组的方法 1. split() - 最常用的方法 功能描述:使用指定的分隔符将字符串分割成字符串数组 语法: str.split([separator[, limit]]) 参数: * separator:指定表示每个拆分点的字符串,如果省略,则返回包含整个字符串的数组 * limit:可选,限制返回的数组片段数量 示例: const str = "apple,banana,orange"; const arr = str.split(","); // 结果: ["apple", "banana", "orange"] const str2 = "hello"; const

By Ne0inhk
深入理解 HTML5 Web Workers:提升网页性能的关键技术解析

深入理解 HTML5 Web Workers:提升网页性能的关键技术解析

深入理解 HTML5 Web Workers:提升网页性能的关键技术解析 * 引言 * 1. 什么是 Web Workers? * Web Workers 的特点: * 2. Web Workers 的使用方式 * 2.1 创建一个 Web Worker * 步骤 1:创建 Worker 文件 * 步骤 2:在主线程中调用 Worker * 3. Web Workers 的高级应用 * 3.1 使用 `Blob` 方式创建 Worker * 3.2 终止 Worker * 4. Web Workers 的应用场景 * 示例:

By Ne0inhk