1. 对象
1.1 什么是对象
在 JavaScript 中,对象( Object)是一种复合数据类型,用于存储多个相关的数据和功能。
对象就像是现实生活中的"东西",例如:
- 一部手机: 有品牌、型号、颜色等属性,有打电话、发短信等方法
- 一个学生: 有姓名、年龄、学号等属性,有学习、考试等方法
- 一本书: 有书名、作者、出版社等属性,有阅读、借阅等方法
对象的特点:
- 键值对集合: 对象由一组属性(键)和对应的值组成
- 无序性: 对象中的属性没有固定顺序
- 动态性: 可以随时添加、删除、修改属性
- 引用类型: 对象是引用类型,存储的是内存地址
对象的组成:
// 一个学生对象示例
const student = {
// 属性: 存储数据
name: '张三',
age: 18,
gender: '男',
major: '计算机科学',
// 方法: 存储函数
sayHello: function() {
console.log('大家好,我是' + this.name);
},
study: function(subject) {
console.log(this.name + '正在学习' + subject);
}
};对象与基本类型的区别:
| 类型 | 特点 | 示例 |
|---|---|---|
| 基本类型 | 存储单个值,按值传递 | let a = 10; |
| 对象类型 | 存储多个值,按引用传递 | let obj = { name: '张三' }; |
// 基本类型 - 按值传递
let num1 = 10;
let num2 = num1;
num2 = 20;
console.log(num1); // 10, num1 不受影响
// 对象类型 - 按引用传递
let obj1 = { name: '张三' };
let obj2 = obj1; // obj2 指向同一个对象
obj2.name = '李四';
console.log(obj1.name); // 李四, obj1 也被修改1.2 对象的使用
1.2.1 对象的基本语法
创建对象的方式:
// 方式一: 字面量创建 (推荐)
const person = {
name: '张三',
age: 18
};
// 方式二: new Object() 创建
const person2 = new Object();
person2.name = '李四';
person2.age = 20;
// 方式三: 构造函数创建
function Person(name, age) {
this.name = name;
this.age = age;
}
const person3 = new Person('王五', 22);对象字面量语法:
const obj = {
// 属性名: 属性值
name: '张三',
age: 18,
isStudent: true,
hobbies: ['读书', '运动', '编程'],
// 方法 (函数)
greet: function() {
console.log('你好,我是' + this.name);
},
// ES6 简写方法
sayHello() {
console.log('你好,我是' + this.name);
}
};属性名的命名规则:
const obj = {
// 标准命名
name: '张三',
age: 18,
_private: '私有属性',
// 使用特殊字符的属性名需要加引号
'user-name': 'user001',
'first name': '张',
'class': '一班',
// 数字作为属性名
1: '第一个值',
2: '第二个值'
};
// 特殊属性名的访问
console.log(obj['user-name']); // user001
console.log(obj['1']); // 第一个值1.2.2 对象属性的增删改查
1. 查询属性
const person = {
name: '张三',
age: 18,
gender: '男',
score: 90
};
// 方式一: 点表示法 (推荐)
console.log(person.name); // 张三
console.log(person.age); // 18
// 方式二: 方括号表示法 (适用于动态属性名)
console.log(person['name']); // 张三
console.log(person['age']); // 18
// 动态属性名的使用
const propName = 'gender';
console.log(person[propName]); // 男
// 检查属性是否存在
console.log('name' in person); // true
console.log('address' in person); // false
console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('address')); // false2. 添加属性
const person = {
name: '张三',
age: 18
};
// 添加单个属性
person.gender = '男';
person['school'] = '清华大学';
console.log(person);
// { name: '张三', age: 18, gender: '男', school: '清华大学' }
// 动态添加属性
const newProps = {
hobbies: ['读书', '运动'],
score: 90,
isStudent: true
};
Object.assign(person, newProps);
console.log(person);
// { name: '张三', age: 18, gender: '男', school: '清华大学',
// hobbies: ['读书', '运动'], score: 90, isStudent: true }3. 修改属性
const person = {
name: '张三',
age: 18,
score: 80
};
// 修改属性值
person.name = '李四';
person['age'] = 20;
person.score = 95;
console.log(person);
// { name: '李四', age: 20, score: 95 }
// 批量修改属性
Object.assign(person, {
name: '王五',
score: 98
});
console.log(person);
// { name: '王五', age: 20, score: 98 }4. 删除属性
const person = {
name: '张三',
age: 18,
gender: '男',
score: 90
};
// 删除属性
delete person.gender;
delete person['score'];
console.log(person);
// { name: '张三', age: 18 }
// 检查删除结果
console.log('gender' in person); // false
console.log('score' in person); // false属性操作的完整示例:
const student = {
name: '张三',
age: 18
};
console.log('初始对象:', student);
// { name: '张三', age: 18 }
// 查询
console.log('姓名:', student.name); // 张三
// 添加
student.gender = '男';
student.major = '计算机科学';
console.log('添加属性后:', student);
// { name: '张三', age: 18, gender: '男', major: '计算机科学' }
// 修改
student.age = 19;
student.major = '软件工程';
console.log('修改属性后:', student);
// { name: '张三', age: 19, gender: '男', major: '软件工程' }
// 删除
delete student.gender;
console.log('删除属性后:', student);
// { name: '张三', age: 19, major: '软件工程' }1.2.3 对象方法的定义与使用
定义对象方法:
// 方式一: 传统方式
const person = {
name: '张三',
age: 18,
sayHello: function() {
console.log('你好,我是' + this.name);
}
};
// 方式二: ES6 简写方式 (推荐)
const person2 = {
name: '李四',
age: 20,
sayHello() {
console.log('你好,我是' + this.name);
}
};
// 方式三: 箭头函数 (注意:this 指向问题)
const person3 = {
name: '王五',
age: 22,
sayHello: () => {
console.log('你好,我是' + this.name); // undefined
}
};调用对象方法:
const person = {
name: '张三',
age: 18,
sayHello() {
console.log('你好,我是' + this.name);
},
introduce() {
console.log(`我叫${this.name},今年${this.age}岁`);
}
};
// 调用方法
person.sayHello(); // 你好,我是张三
person.introduce(); // 我叫张三,今年18岁方法参数的使用:
const calculator = {
add(a, b) {
return a + b;
},
subtract(a, b) {
return a - b;
},
multiply(a, b) {
return a * b;
},
divide(a, b) {
if (b === 0) {
throw new Error('除数不能为0');
}
return a / b;
}
};
// 调用带参数的方法
console.log(calculator.add(5, 3)); // 8
console.log(calculator.subtract(5, 3)); // 2
console.log(calculator.multiply(5, 3)); // 15
console.log(calculator.divide(6, 3)); // 2this 关键字:
const person = {
name: '张三',
age: 18,
// this 指向调用这个方法的对象
sayHello() {
console.log('this.name =', this.name);
},
compareWith(otherPerson) {
if (this.age > otherPerson.age) {
console.log(this.name + '比' + otherPerson.name + '大');
} else {
console.log(this.name + '比' + otherPerson.name + '小');
}
}
};
const otherPerson = {
name: '李四',
age: 20
};
person.sayHello(); // this.name = 张三
person.compareWith(otherPerson); // 张三比李四小对象的常见方法:
const person = {
name: '张三',
age: 18,
gender: '男',
// 获取信息
getInfo() {
return {
name: this.name,
age: this.age,
gender: this.gender
};
},
// 更新信息
updateInfo(newInfo) {
Object.assign(this, newInfo);
},
// 打印信息
printInfo() {
console.log(`姓名: ${this.name}, 年龄: ${this.age}, 性别: ${this.gender}`);
},
// 判断是否成年
isAdult() {
return this.age >= 18;
}
};
// 使用方法
console.log(person.getInfo());
// { name: '张三', age: 18, gender: '男' }
person.updateInfo({ age: 19, gender: '女' });
console.log(person.getInfo());
// { name: '张三', age: 19, gender: '女' }
person.printInfo();
// 姓名: 张三, 年龄: 19, 性别: 女
console.log(person.isAdult()); // true方法作为回调函数:
const math = {
base: 10,
// 方法可以作为回调函数
add: function(a, b) {
return a + b;
}
};
const numbers = [1, 2, 3, 4, 5];
// 使用对象方法
const doubled = numbers.map(function(num) {
return math.add(num, num);
});
console.log(doubled); // [2, 4, 6, 8, 10]
// 使用对象方法的简化版本
const doubled2 = numbers.map(num => math.add(num, num));
console.log(doubled2); // [2, 4, 6, 8, 10]对象方法的实际应用示例:
// 学生管理系统
const student = {
name: '张三',
studentId: '2024001',
scores: {
math: 90,
english: 85,
chinese: 88
},
// 计算平均分
getAverageScore() {
const scores = Object.values(this.scores);
const sum = scores.reduce((total, score) => total + score, 0);
return (sum / scores.length).toFixed(2);
},
// 获取最高分科目
getMaxScoreSubject() {
let maxSubject = '';
let maxScore = 0;
for (const subject in this.scores) {
if (this.scores[subject] > maxScore) {
maxScore = this.scores[subject];
maxSubject = subject;
}
}
return {
subject: maxSubject,
score: maxScore
};
},
// 更新成绩
updateScore(subject, score) {
if (this.scores.hasOwnProperty(subject)) {
this.scores[subject] = score;
console.log(`${subject} 成绩已更新为 ${score}`);
} else {
console.log('科目不存在');
}
},
// 打印成绩单
printReport() {
console.log(`=== ${this.name} 的成绩单 ===`);
console.log(`学号: ${this.studentId}`);
console.log('----------------');
for (const subject in this.scores) {
console.log(`${subject}: ${this.scores[subject]}`);
}
console.log('----------------');
console.log(`平均分: ${this.getAverageScore()}`);
console.log('==================');
}
};
// 使用学生对象
console.log('平均分:', student.getAverageScore()); // 平均分: 87.67
const maxScore = student.getMaxScoreSubject();
console.log('最高分科目:', maxScore); // 最高分科目: { subject: 'math', score: 90 }
student.updateScore('math', 95); // math 成绩已更新为 95
student.printReport();
// === 张三 的成绩单 ===
// 学号: 2024001
// ----------------
// math: 95
// english: 85
// chinese: 88
// ----------------
// 平均分: 89.33
// ==================对象方法的注意事项:
// 注意1: this 的指向
const obj = {
name: '张三',
// 普通函数 - this 指向对象
regularMethod() {
console.log(this.name); // 张三
},
// 箭头函数 - this 继承外层作用域
arrowMethod: () => {
console.log(this.name); // undefined (在浏览器中可能是 window.name)
}
};
// 注意2: 方法中的嵌套函数
const obj2 = {
name: '李四',
method() {
// 嵌套函数中的 this 不再指向对象
function inner() {
console.log(this.name); // undefined
}
inner();
// 解决方法1: 使用箭头函数
const inner2 = () => {
console.log(this.name); // 李四
};
inner2();
// 解决方法2: 保存 this
const self = this;
function inner3() {
console.log(self.name); // 李四
}
inner3();
}
};
// 注意3: 解构会丢失 this
const obj3 = {
name: '王五',
greet() {
console.log('你好,我是' + this.name);
}
};
const { greet } = obj3;
greet(); // 你好,我是undefined
// 解决方法: 使用 bind
const greet2 = obj3.greet.bind(obj3);
greet2(); // 你好,我是王五1.3 对象的遍历
1.3.1 for...in 循环
for...in 循环用于遍历对象的可枚举属性:
const person = {
name: '张三',
age: 18,
gender: '男',
city: '北京'
};
// 遍历对象属性名(键)
for (let key in person) {
console.log(key); // name, age, gender, city
}
// 遍历对象属性值
for (let key in person) {
console.log(person[key]); // 张三, 18, 男, 北京
}
// 同时遍历键和值
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// name: 张三
// age: 18
// gender: 男
// city: 北京for...in 的注意事项:
// 注意1: 会遍历原型链上的可枚举属性
const obj = { a: 1, b: 2 };
Object.prototype.c = 3; // 添加原型属性
for (let key in obj) {
console.log(key); // a, b, c (包括原型上的 c)
}
// 解决方法: 使用 hasOwnProperty 检查
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key); // a, b (只输出对象自身的属性)
}
}
// 注意2: 属性顺序不一定按创建顺序
const obj2 = {};
obj2.z = 'last';
obj2.a = 'first';
obj2.m = 'middle';
for (let key in obj2) {
console.log(key); // 数字类型先按顺序,字符串类型按插入顺序
}1.3.2 Object.keys()
Object.keys() 返回对象自身可枚举属性的键数组:
const person = {
name: '张三',
age: 18,
gender: '男'
};
// 获取所有键
const keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'gender']
// 结合 forEach 遍历
Object.keys(person).forEach(key => {
console.log(key, person[key]);
});
// name 张三
// age 18
// gender 男1.3.3 Object.values()
Object.values() 返回对象自身可枚举属性的值数组:
const person = {
name: '张三',
age: 18,
gender: '男'
};
// 获取所有值
const values = Object.values(person);
console.log(values); // ['张三', 18, '男']
// 遍历值
Object.values(person).forEach(value => {
console.log(value);
});
// 张三
// 18
// 男1.3.4 Object.entries()
Object.entries() 返回对象自身可枚举属性的键值对数组:
const person = {
name: '张三',
age: 18,
gender: '男'
};
// 获取键值对数组
const entries = Object.entries(person);
console.log(entries);
// [['name', '张三'], ['age', 18], ['gender', '男']]
// 遍历键值对
Object.entries(person).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
// name: 张三
// age: 18
// gender: 男
// 将对象转为 Map
const map = new Map(Object.entries(person));
console.log(map.get('name')); // 张三1.3.5 Object.getOwnPropertyNames()
Object.getOwnPropertyNames() 返回对象自身所有属性(包括不可枚举属性)的键数组:
const obj = { a: 1, b: 2 };
Object.defineProperty(obj, 'c', {
value: 3,
enumerable: false // 不可枚举
});
console.log(Object.keys(obj)); // ['a', 'b'] (不包括不可枚举属性)
console.log(Object.getOwnPropertyNames(obj)); // ['a', 'b', 'c'] (包括所有属性)1.3.6 遍历方法对比
| 方法 | 返回值 | 包含不可枚举属性 | 包含原型链属性 |
|---|---|---|---|
for...in | 键 | 否 | 是 |
Object.keys() | 键数组 | 否 | 否 |
Object.values() | 值数组 | 否 | 否 |
Object.entries() | 键值对数组 | 否 | 否 |
Object.getOwnPropertyNames() | 键数组 | 是 | 否 |
1.3.7 实际应用示例
示例1: 对象深拷贝
function deepCopy(obj) {
const copy = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
copy[key] = deepCopy(obj[key]); // 递归拷贝
} else {
copy[key] = obj[key];
}
}
}
return copy;
}
const original = {
name: '张三',
age: 18,
address: {
city: '北京',
district: '海淀区'
}
};
const copied = deepCopy(original);
console.log(copied);示例2: 对象属性统计
function countProperties(obj) {
const stats = {
total: 0,
types: {
string: 0,
number: 0,
boolean: 0,
object: 0,
function: 0,
undefined: 0
}
};
Object.values(obj).forEach(value => {
stats.total++;
const type = typeof value;
if (stats.types.hasOwnProperty(type)) {
stats.types[type]++;
}
});
return stats;
}
const data = {
name: '张三',
age: 18,
isStudent: true,
address: { city: '北京' },
greet: function() { console.log('你好'); },
nothing: undefined
};
console.log(countProperties(data));
// {
// total: 6,
// types: {
// string: 1,
// number: 1,
// boolean: 1,
// object: 1,
// function: 1,
// undefined: 1
// }
// }示例3: 对象属性过滤
function filterObject(obj, condition) {
const result = {};
Object.entries(obj).forEach(([key, value]) => {
if (condition(key, value)) {
result[key] = value;
}
});
return result;
}
const person = {
name: '张三',
age: 18,
gender: '男',
city: '北京',
score: 90,
isStudent: true
};
// 过滤出字符串类型的属性
const stringProps = filterObject(person, (key, value) => typeof value === 'string');
console.log(stringProps);
// { name: '张三', gender: '男', city: '北京' }
// 过滤出数值类型的属性
const numberProps = filterObject(person, (key, value) => typeof value === 'number');
console.log(numberProps);
// { age: 18, score: 90 }示例4: 对象属性转换
function transformObject(obj, transformFn) {
const result = {};
Object.entries(obj).forEach(([key, value]) => {
result[key] = transformFn(key, value);
});
return result;
}
const data = {
name: 'zhang san',
age: '18',
score: '90'
};
// 将字符串数字转为数字
const transformed = transformObject(data, (key, value) => {
if (!isNaN(value) && value !== '') {
return Number(value);
}
return value;
});
console.log(transformed);
// { name: 'zhang san', age: 18, score: 90 }示例5: 对象比较
function compareObjects(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (!obj2.hasOwnProperty(key)) {
return false;
}
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
const obj1 = { name: '张三', age: 18 };
const obj2 = { name: '张三', age: 18 };
const obj3 = { name: '李四', age: 18 };
console.log(compareObjects(obj1, obj2)); // true
console.log(compareObjects(obj1, obj3)); // false示例6: 对象合并
function mergeObjects(...objects) {
const result = {};
objects.forEach(obj => {
Object.entries(obj).forEach(([key, value]) => {
result[key] = value;
});
});
return result;
}
const obj1 = { name: '张三', age: 18 };
const obj2 = { gender: '男', city: '北京' };
const obj3 = { score: 90, isStudent: true };
const merged = mergeObjects(obj1, obj2, obj3);
console.log(merged);
// { name: '张三', age: 18, gender: '男', city: '北京', score: 90, isStudent: true }1.3.8 遍历的注意事项
// 注意1: 遍历时不要直接修改对象
const obj = { a: 1, b: 2, c: 3 };
// 错误: 直接修改可能导致问题
for (let key in obj) {
delete obj[key]; // 可能导致意外的行为
}
// 正确: 创建新对象
const filtered = {};
for (let key in obj) {
if (obj[key] > 1) {
filtered[key] = obj[key];
}
}
console.log(filtered); // { b: 2, c: 3 }
// 注意2: 使用 const 避免意外的键修改
Object.keys(obj).forEach(key => {
// key = 'newKey'; // 不会影响原对象
console.log(obj[key]);
});
// 注意3: 处理嵌套对象
const nestedObj = {
user: {
name: '张三',
info: {
age: 18,
address: {
city: '北京'
}
}
}
};
// 递归遍历嵌套对象
function traverseObject(obj, path = '') {
Object.entries(obj).forEach(([key, value]) => {
const currentPath = path ? `${path}.${key}` : key;
if (typeof value === 'object' && value !== null) {
traverseObject(value, currentPath);
} else {
console.log(`${currentPath}: ${value}`);
}
});
}
traverseObject(nestedObj);
// user.name: 张三
// user.info.age: 18
// user.info.address.city: 北京1.3.9 最佳实践
// 最佳实践1: 优先使用 Object.keys/values/entries
const obj = { name: '张三', age: 18 };
// 推荐: 使用 Object.keys
Object.keys(obj).forEach(key => {
console.log(key, obj[key]);
});
// 其次: 使用 for...in (记得用 hasOwnProperty)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}
// 最佳实践2: 根据需求选择合适的方法
// 只需要键: Object.keys()
// 只需要值: Object.values()
// 需要键值对: Object.entries() 或 for...in
// 最佳实践3: 性能考虑
const largeObj = {}; // 假设有很多属性
// 性能较好: for...in
for (let key in largeObj) {
if (largeObj.hasOwnProperty(key)) {
// 处理
}
}
// 现代浏览器性能也不错: Object.keys()
Object.keys(largeObj).forEach(key => {
// 处理
});2. JS内置对象
JavaScript 提供了许多内置对象,这些对象提供了各种功能和方法,可以直接使用。
2.1 Math 对象
Math 对象用于执行数学任务,它不是构造函数,不需要用 new 调用。
2.1.1 常用数学常量
// 圆周率
console.log(Math.PI); // 3.141592653589793
// 自然对数的底
console.log(Math.E); // 2.718281828459045
// 其他常量
console.log(Math.SQRT2); // 2 的平方根: 1.4142135623730951
console.log(Math.SQRT1_2); // 1/2 的平方根: 0.7071067811865476
console.log(Math.LN2); // 2 的自然对数: 0.6931471805599453
console.log(Math.LN10); // 10 的自然对数: 2.302585092994046
console.log(Math.LOG2E); // 以 2 为底 e 的对数: 1.4426950408889634
console.log(Math.LOG10E); // 以 10 为底 e 的对数: 0.43429448190325182.1.2 常用数学方法
取整方法
const num = 3.7;
// 向上取整: 返回大于等于给定数字的最小整数
console.log(Math.ceil(3.1)); // 4
console.log(Math.ceil(3.9)); // 4
console.log(Math.ceil(-3.9)); // -3
// 向下取整: 返回小于等于给定数字的最大整数
console.log(Math.floor(3.9)); // 3
console.log(Math.floor(3.1)); // 3
console.log(Math.floor(-3.1)); // -4
// 四舍五入: 返回最接近的整数
console.log(Math.round(3.4)); // 3
console.log(Math.round(3.5)); // 4
console.log(Math.round(-3.5)); // -3 (注意: -3.5 四舍五入到 -3)
// 截断小数: 返回数字的整数部分
console.log(Math.trunc(3.9)); // 3
console.log(Math.trunc(-3.9)); // -3
// 取整数部分 (使用位运算)
console.log(~~3.9); // 3
console.log(~~-3.9); // -3最大值和最小值
// 获取多个数字中的最大值
console.log(Math.max(1, 5, 3, 9, 2)); // 9
console.log(Math.max(...[1, 5, 3, 9, 2])); // 9
// 获取多个数字中的最小值
console.log(Math.min(1, 5, 3, 9, 2)); // 1
console.log(Math.min(...[1, 5, 3, 9, 2])); // 1
// 应用: 获取数组中的最大值和最小值
const numbers = [15, 8, 23, 42, 7];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(`最大值: ${max}, 最小值: ${min}`); // 最大值: 42, 最小值: 7幂运算和开方
// 幂运算: x 的 y 次方
console.log(Math.pow(2, 3)); // 8 (2 的 3 次方)
console.log(Math.pow(5, 2)); // 25 (5 的 2 次方)
console.log(Math.pow(4, 0.5)); // 2 (4 的 0.5 次方 = 平方根)
// 平方根
console.log(Math.sqrt(16)); // 4
console.log(Math.sqrt(2)); // 1.4142135623730951
console.log(Math.sqrt(-1)); // NaN
// 立方根
console.log(Math.cbrt(8)); // 2
console.log(Math.cbrt(27)); // 3绝对值
console.log(Math.abs(5)); // 5
console.log(Math.abs(-5)); // 5
console.log(Math.abs(-3.14)); // 3.14
console.log(Math.abs(0)); // 0随机数
// 生成 0 到 1 之间的随机小数 (包括 0, 不包括 1)
console.log(Math.random()); // 例如: 0.123456789...
// 生成指定范围内的随机整数 (例如: 0-9)
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
console.log(getRandomInt(10)); // 0-9 之间的整数
// 生成指定范围内的随机整数 (例如: min-max)
function getRandomIntInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandomIntInRange(1, 10)); // 1-10 之间的整数
// 生成随机颜色
function getRandomColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
console.log(getRandomColor()); // 例如: rgb(123, 45, 67)
// 从数组中随机选择一个元素
function randomChoice(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
const fruits = ['苹果', '香蕉', '橙子', '葡萄'];
console.log(randomChoice(fruits)); // 随机选择一个水果三角函数
// 角度转弧度
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
// 弧度转角度
function toDegrees(radians) {
return radians * (180 / Math.PI);
}
// 正弦
console.log(Math.sin(Math.PI / 2)); // 1 (90 度的正弦值)
console.log(Math.sin(0)); // 0
// 余弦
console.log(Math.cos(0)); // 1
console.log(Math.cos(Math.PI)); // -1 (180 度的余弦值)
// 正切
console.log(Math.tan(Math.PI / 4)); // 1 (45 度的正切值)
// 反正弦
console.log(Math.asin(1)); // 1.5707963267948966 (Math.PI / 2)2.1.3 Math 对象的实际应用
应用1: 计算圆的面积和周长
function calculateCircle(radius) {
const area = Math.PI * Math.pow(radius, 2);
const circumference = 2 * Math.PI * radius;
return {
area: area.toFixed(2),
circumference: circumference.toFixed(2)
};
}
console.log(calculateCircle(5));
// { area: "78.54", circumference: "31.42" }应用2: 随机生成验证码
function generateCode(length = 4) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < length; i++) {
code += chars[Math.floor(Math.random() * chars.length)];
}
return code;
}
console.log(generateCode()); // 例如: A7B9
console.log(generateCode(6)); // 例如: X3Y5Z2应用3: 数值范围限制
function clamp(value, min, max) {
return Math.max(min, Math.min(value, max));
}
console.log(clamp(50, 0, 100)); // 50 (在范围内)
console.log(clamp(-10, 0, 100)); // 0 (低于最小值)
console.log(clamp(150, 0, 100)); // 100 (高于最大值)2.2 Date 对象
Date 对象用于处理日期和时间。
2.2.1 创建日期对象
// 创建当前日期时间
const now = new Date();
console.log(now); // 当前日期和时间
// 创建指定日期
const date1 = new Date('2024-01-15');
console.log(date1); // 2024-01-15T00:00:00.000Z
const date2 = new Date(2024, 0, 15); // 月份从 0 开始,0 表示 1 月
console.log(date2); // 2024-01-15T00:00:00.000Z
const date3 = new Date(2024, 0, 15, 10, 30, 0); // 年, 月, 日, 时, 分, 秒
console.log(date3); // 2024-01-15T02:30:00.000Z (北京时间会自动转换)
// 使用时间戳创建
const date4 = new Date(1705276800000);
console.log(date4); // 2024-01-15T00:00:00.000Z2.2.2 获取日期和时间
const date = new Date();
// 获取年份 (4位)
console.log(date.getFullYear()); // 例如: 2024
// 获取月份 (0-11)
console.log(date.getMonth()); // 0 表示 1 月,11 表示 12 月
// 获取日期 (1-31)
console.log(date.getDate()); // 例如: 15
// 获取星期 (0-6, 0 表示周日)
console.log(date.getDay()); // 例如: 1 (周一)
// 获取小时 (0-23)
console.log(date.getHours()); // 例如: 14
// 获取分钟 (0-59)
console.log(date.getMinutes()); // 例如: 30
// 获取秒 (0-59)
console.log(date.getSeconds()); // 例如: 45
// 获取毫秒 (0-999)
console.log(date.getMilliseconds()); // 例如: 123
// 获取时间戳 (从 1970-01-01 00:00:00 UTC 开始的毫秒数)
console.log(date.getTime()); // 例如: 1705276800000
console.log(Date.now()); // 当前时间的时间戳2.2.3 设置日期和时间
const date = new Date();
// 设置年份
date.setFullYear(2025);
console.log(date.getFullYear()); // 2025
// 设置月份 (0-11)
date.setMonth(11); // 12 月
console.log(date.getMonth()); // 11
// 设置日期
date.setDate(25);
console.log(date.getDate()); // 25
// 设置小时
date.setHours(10);
console.log(date.getHours()); // 10
// 设置分钟
date.setMinutes(30);
console.log(date.getMinutes()); // 30
// 设置秒
date.setSeconds(0);
console.log(date.getSeconds()); // 0
// 设置时间戳
date.setTime(1705276800000);
console.log(date.getTime()); // 17052768000002.2.4 日期格式化
const date = new Date();
// toString() - 返回本地日期字符串
console.log(date.toString());
// 例如: Mon Jan 15 2024 14:30:45 GMT+0800 (中国标准时间)
// toDateString() - 只返回日期部分
console.log(date.toDateString());
// 例如: Mon Jan 15 2024
// toTimeString() - 只返回时间部分
console.log(date.toTimeString());
// 例如: 14:30:45 GMT+0800 (中国标准时间)
// toISOString() - 返回 ISO 8601 格式
console.log(date.toISOString());
// 例如: 2024-01-15T06:30:45.000Z
// 自定义格式化
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
console.log(formatDate(date)); // 例如: 2024-01-15 14:30:45
// 格式化为中文日期
function formatChineseDate(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const weekDays = ['日', '一', '二', '三', '四', '五', '六'];
const weekDay = weekDays[date.getDay()];
return `${year}年${month}月${day}日 星期${weekDay}`;
}
console.log(formatChineseDate(date)); // 例如: 2024年1月15日 星期一2.2.5 日期计算
// 计算两个日期之间的天数差
function daysBetween(date1, date2) {
const diffTime = Math.abs(date2 - date1);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
const start = new Date('2024-01-01');
const end = new Date('2024-01-15');
console.log(daysBetween(start, end)); // 14
// 添加天数
function addDays(date, days) {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
const today = new Date();
const nextWeek = addDays(today, 7);
console.log(nextWeek); // 一周后的日期
// 判断是否是今天
function isToday(date) {
const today = new Date();
return date.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear();
}
// 判断是否是工作日 (周一到周五)
function isWeekday(date) {
const day = date.getDay();
return day > 0 && day < 6; // 0 是周日,6 是周六
}
// 计算倒计时
function countdown(targetDate) {
const now = new Date();
const target = new Date(targetDate);
const diff = target - now;
if (diff <= 0) {
return '时间已到';
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return `${days}天 ${hours}小时 ${minutes}分钟 ${seconds}秒`;
}
console.log(countdown('2024-12-31'));2.3 Array 对象
Array 对象用于处理数组,提供了丰富的方法。
2.3.1 数组创建
// 方式一: 字面量创建
const arr1 = [1, 2, 3, 4, 5];
// 方式二: 构造函数创建
const arr2 = new Array(1, 2, 3, 4, 5);
// 方式三: 创建指定长度的空数组
const arr3 = new Array(5); // [undefined × 5]
// 方式四: Array.of() (推荐)
const arr4 = Array.of(1, 2, 3, 4, 5);
const arr5 = Array.of(5); // [5] (注意: 与 new Array(5) 不同)2.3.2 数组常用方法
添加和删除元素
const fruits = ['苹果', '香蕉'];
// push() - 在末尾添加元素
fruits.push('橙子');
console.log(fruits); // ['苹果', '香蕉', '橙子']
// pop() - 删除末尾元素
const last = fruits.pop();
console.log(last); // 橙子
console.log(fruits); // ['苹果', '香蕉']
// unshift() - 在开头添加元素
fruits.unshift('葡萄');
console.log(fruits); // ['葡萄', '苹果', '香蕉']
// shift() - 删除开头元素
const first = fruits.shift();
console.log(first); // 葡萄
console.log(fruits); // ['苹果', '香蕉']数组转换
// toString() - 转为字符串
const arr = [1, 2, 3, 4, 5];
console.log(arr.toString()); // "1,2,3,4,5"
// join() - 用指定分隔符连接成字符串
console.log(arr.join('-')); // "1-2-3-4-5"
console.log(arr.join('')); // "12345"
// split() - 字符串转数组
const str = '1,2,3,4,5';
console.log(str.split(',')); // ['1', '2', '3', '4', '5']数组查找
const fruits = ['苹果', '香蕉', '橙子', '葡萄', '苹果'];
// indexOf() - 查找元素,返回索引,不存在返回 -1
console.log(fruits.indexOf('苹果')); // 0
console.log(fruits.indexOf('梨子')); // -1
console.log(fruits.indexOf('苹果', 1)); // 4 (从索引 1 开始查找)
// lastIndexOf() - 从后往前查找
console.log(fruits.lastIndexOf('苹果')); // 4
// includes() - 判断是否包含元素
console.log(fruits.includes('苹果')); // true
console.log(fruits.includes('梨子')); // false
// find() - 查找符合条件的第一个元素
const numbers = [1, 5, 10, 15, 20];
const found = numbers.find(num => num > 10);
console.log(found); // 15
// findIndex() - 查找符合条件的第一个元素的索引
const index = numbers.findIndex(num => num > 10);
console.log(index); // 3数组迭代
const numbers = [1, 2, 3, 4, 5];
// forEach() - 遍历数组
numbers.forEach((num, index, array) => {
console.log(`索引 ${index}: ${num}`);
});
// map() - 映射,返回新数组
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter() - 过滤,返回符合条件的新数组
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
// reduce() - 归约,累加
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
// some() - 是否有元素满足条件
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true
// every() - 是否所有元素都满足条件
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true数组排序
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
// sort() - 排序 (默认按字符串排序)
numbers.sort();
console.log(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// 数字排序 (需要提供比较函数)
const nums = [3, 1, 4, 1, 5, 9, 2, 6];
nums.sort((a, b) => a - b); // 升序
console.log(nums); // [1, 1, 2, 3, 4, 5, 6, 9]
nums.sort((a, b) => b - a); // 降序
console.log(nums); // [9, 6, 5, 4, 3, 2, 1, 1]
// 对象数组排序
const users = [
{ name: '张三', age: 25 },
{ name: '李四', age: 20 },
{ name: '王五', age: 30 }
];
users.sort((a, b) => a.age - b.age);
console.log(users);
// [
// { name: '李四', age: 20 },
// { name: '张三', age: 25 },
// { name: '王五', age: 30 }
// ]
// reverse() - 反转数组
const arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]2.3.3 数组去重
// 方法一: 使用 Set
const arr1 = [1, 2, 2, 3, 4, 4, 5];
const unique1 = [...new Set(arr1)];
console.log(unique1); // [1, 2, 3, 4, 5]
// 方法二: 使用 filter 和 indexOf
const arr2 = [1, 2, 2, 3, 4, 4, 5];
const unique2 = arr2.filter((item, index) => arr2.indexOf(item) === index);
console.log(unique2); // [1, 2, 3, 4, 5]
// 方法三: 使用 reduce
const arr3 = [1, 2, 2, 3, 4, 4, 5];
const unique3 = arr3.reduce((acc, item) => {
if (!acc.includes(item)) {
acc.push(item);
}
return acc;
}, []);
console.log(unique3); // [1, 2, 3, 4, 5]2.4 String 对象
String 对象用于处理字符串。
2.4.1 字符串常用方法
const str = 'Hello World';
// 获取长度
console.log(str.length); // 11
// 获取字符
console.log(str.charAt(0)); // 'H'
console.log(str[0]); // 'H' (推荐)
// 获取字符编码
console.log(str.charCodeAt(0)); // 72
// 查找子串
console.log(str.indexOf('World')); // 6
console.log(str.indexOf('world')); // -1 (大小写敏感)
console.log(str.includes('World')); // true
// 判断开头和结尾
console.log(str.startsWith('Hello')); // true
console.log(str.endsWith('World')); // true
// 截取字符串
console.log(str.slice(0, 5)); // 'Hello'
console.log(str.slice(6)); // 'World'
console.log(str.substring(0, 5)); // 'Hello'
console.log(str.substr(6, 5)); // 'World'
// 大小写转换
console.log(str.toUpperCase()); // 'HELLO WORLD'
console.log(str.toLowerCase()); // 'hello world'
// 去除空白
const str2 = ' hello ';
console.log(str2.trim()); // 'hello'
console.log(str2.trimStart()); // 'hello '
console.log(str2.trimEnd()); // ' hello'2.4.2 字符串替换和分割
const str = 'Hello World Hello';
// replace() - 替换 (只替换第一个)
console.log(str.replace('Hello', 'Hi')); // 'Hi World Hello'
// replaceAll() - 替换所有
console.log(str.replaceAll('Hello', 'Hi')); // 'Hi World Hi'
// split() - 分割字符串
const str3 = 'apple,banana,orange';
console.log(str3.split(',')); // ['apple', 'banana', 'orange']
// 限制分割次数
console.log(str3.split(',', 2)); // ['apple', 'banana']2.4.3 字符串重复和填充
// repeat() - 重复字符串
console.log('abc'.repeat(3)); // 'abcabcabc'
// padStart() - 开头填充
console.log('5'.padStart(2, '0')); // '05'
console.log('123'.padStart(5, '0')); // '00123'
// padEnd() - 结尾填充
console.log('5'.padEnd(2, '0')); // '50'
console.log('123'.padEnd(5, '0')); // '12300'2.5 JSON 对象
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。
2.5.1 JSON.parse()
将 JSON 字符串转换为 JavaScript 对象:
const jsonStr = '{"name": "张三", "age": 18, "isStudent": true}';
// 解析 JSON 字符串
const obj = JSON.parse(jsonStr);
console.log(obj); // { name: '张三', age: 18, isStudent: true }
console.log(obj.name); // 张三
// 解析数组
const arrStr = '[1, 2, 3, 4, 5]';
const arr = JSON.parse(arrStr);
console.log(arr); // [1, 2, 3, 4, 5]
// 带错误处理
try {
const invalidJson = '{"name": "张三", age: 18}'; // 缺少引号
const result = JSON.parse(invalidJson);
} catch (error) {
console.log('JSON 解析失败:', error.message);
}2.5.2 JSON.stringify()
将 JavaScript 对象转换为 JSON 字符串:
const obj = {
name: '张三',
age: 18,
isStudent: true,
hobbies: ['读书', '运动']
};
// 转换为 JSON 字符串
const jsonStr = JSON.stringify(obj);
console.log(jsonStr);
// {"name":"张三","age":18,"isStudent":true,"hobbies":["读书","运动"]}
// 格式化输出 (缩进 2 个空格)
const formatted = JSON.stringify(obj, null, 2);
console.log(formatted);
// {
// "name": "张三",
// "age": 18,
// "isStudent": true,
// "hobbies": [
// "读书",
// "运动"
// ]
// }
// 过滤属性
const filtered = JSON.stringify(obj, ['name', 'age']);
console.log(filtered); // {"name":"张三","age":18}2.5.3 JSON 实际应用
// 存储数据到 localStorage
const user = {
id: 1,
name: '张三',
email: 'zhangsan@example.com'
};
// 存储
localStorage.setItem('user', JSON.stringify(user));
// 读取
const storedUser = JSON.parse(localStorage.getItem('user'));
console.log(storedUser); // { id: 1, name: '张三', email: 'zhangsan@example.com' }
// 深拷贝对象
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
const original = { name: '张三', age: 18 };
const cloned = deepClone(original);
console.log(cloned); // { name: '张三', age: 18 }