【JS基础-Day5】对象与内置对象
📺 对应视频:P64-P77 | 🎯 核心目标:掌握对象的CRUD操作、遍历对象、Math内置对象及引用类型原理
一、对象基础
1.1 什么是对象?
对象是键值对的集合,用来描述一个有多个属性的事物。
// 现实类比:
// 一个人 → 对象
// 姓名、年龄、性别 → 属性
// 走路、说话、吃饭 → 方法(函数作为属性值)
let person = {
name: '张三', // 属性(键: 值)
age: 18,
gender: '男',
greet: function() { // 方法
console.log(`我叫${this.name}`)
}
}
1.2 创建对象
// 方式一:对象字面量(最常用)
let obj = {
key1: value1,
key2: value2
}
// 方式二:new Object()
let obj2 = new Object()
obj2.name = '张三'
// 方式三:构造函数(进阶,Day12详解)
function Person(name, age) {
this.name = name
this.age = age
}
let p = new Person('张三', 18)
二、对象的 CRUD
2.1 读取属性(查)
let person = { name: '张三', age: 18, 'my-job': '工程师' }
// 点语法(常用)
console.log(person.name) // '张三'
console.log(person.age) // 18
// 方括号语法(属性名含特殊字符、或属性名是变量时必须用)
console.log(person['name']) // '张三'
console.log(person['my-job']) // '工程师'(含连字符的属性名)
let key = 'age'
console.log(person[key]) // 18(动态属性名)
console.log(person.key) // undefined(把 key 当属性名了)
2.2 修改属性(改)
let person = { name: '张三', age: 18 }
person.name = '李四' // 修改已有属性
person['age'] = 20 // 方括号语法修改
2.3 增加属性(增)
let person = { name: '张三' }
person.gender = '男' // 直接赋值新属性
person['hobby'] = '打篮球'
// 结果:{ name: '张三', gender: '男', hobby: '打篮球' }
2.4 删除属性(删)
let person = { name: '张三', age: 18, gender: '男' }
delete person.gender // 删除属性
console.log(person) // { name: '张三', age: 18 }
三、遍历对象
3.1 for...in 遍历
let person = { name: '张三', age: 18, gender: '男' }
for (let key in person) {
console.log(key) // 属性名:name, age, gender
console.log(person[key]) // 属性值:张三, 18, 男
}
⚠️
for...in会遍历原型链上的可枚举属性,通常配合hasOwnProperty过滤
3.2 Object 方法遍历(推荐)
let person = { name: '张三', age: 18, gender: '男' }
// 获取所有键
Object.keys(person) // ['name', 'age', 'gender']
// 获取所有值
Object.values(person) // ['张三', 18, '男']
// 获取所有键值对
Object.entries(person) // [['name','张三'], ['age',18], ['gender','男']]
// 遍历示例
Object.keys(person).forEach(key => {
console.log(`${key}: ${person[key]}`)
})
四、对象方法
4.1 对象中的方法
let calculator = {
result: 0,
add(num) { // ES6 简写方法语法
this.result += num
return this // 返回 this 支持链式调用
},
subtract(num) {
this.result -= num
return this
},
getResult() {
return this.result
}
}
// 链式调用
calculator.add(10).add(5).subtract(3).getResult() // 12
4.2 this 关键字(初步理解)
let person = {
name: '张三',
greet() {
console.log(this.name) // this 指向调用该方法的对象
}
}
person.greet() // '张三'(this = person)
// 注意:this 指向在运行时确定,不是在定义时
const fn = person.greet
fn() // undefined(严格模式)或全局对象(this 丢失!)
五、内置对象 Math
5.1 Math 常用属性
Math.PI // 3.141592653589793(圆周率)
Math.E // 2.718281828459045(自然常数)
Math.LN2 // 0.6931471805599453
Math.SQRT2 // 1.4142135623730951
5.2 Math 常用方法
// 取整
Math.floor(4.9) // 4 向下取整(地板)
Math.ceil(4.1) // 5 向上取整(天花板)
Math.round(4.5) // 5 四舍五入
Math.trunc(4.9) // 4 去掉小数部分(ES6)
Math.trunc(-4.9) // -4(注意与 floor 的区别,floor(-4.9) = -5)
// 绝对值
Math.abs(-10) // 10
Math.abs(10) // 10
// 最大最小值
Math.max(1, 2, 3) // 3
Math.min(1, 2, 3) // 1
Math.max(...[1, 5, 3]) // 5(展开数组)
// 幂运算和开方
Math.pow(2, 10) // 1024(2的10次方)
Math.sqrt(16) // 4(平方根)
Math.cbrt(27) // 3(立方根)
// 对数
Math.log(Math.E) // 1(自然对数)
Math.log2(8) // 3
Math.log10(1000) // 3
5.3 Math.random() 随机数
// Math.random() 返回 [0, 1) 之间的浮点数
Math.random() // 0.7234...(每次不同)
// 生成 [min, max) 的整数
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
getRandomInt(1, 10) // 1-9 之间的整数
// 生成 [min, max] 的整数(包含 max)
function getRandomIntInclusive(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
getRandomIntInclusive(1, 6) // 模拟骰子:1-6
// 数组随机取一个元素
function randomItem(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
randomItem(['石头', '剪刀', '布']) // 随机一个
六、引用类型 vs 值类型
6.1 根本区别
// 值类型(基本类型):存储值本身,赋值是复制
let a = 10
let b = a // b 是 a 的副本
b = 20
console.log(a) // 10(a 不受影响)
// 引用类型:存储的是内存地址,赋值是复制地址
let obj1 = { name: '张三' }
let obj2 = obj1 // obj2 指向同一个对象
obj2.name = '李四'
console.log(obj1.name) // '李四'(obj1 也变了!)
内存示意图:
值类型:
a → [10]
b → [20](独立的副本)
引用类型:
obj1 → 地址0x001 → { name: '李四' }
obj2 → 地址0x001 ↗(指向同一个对象)
6.2 函数传参的影响
// 值类型传参:传的是副本,不影响原始变量
function increment(n) {
n++
}
let num = 10
increment(num)
console.log(num) // 10(未被修改)
// 引用类型传参:传的是地址,会修改原始对象
function addProp(obj) {
obj.job = '工程师'
}
let person = { name: '张三' }
addProp(person)
console.log(person) // { name: '张三', job: '工程师' }(被修改了!)
七、其他常用内置对象预览
// Date 对象(后面Web APIs详讲)
let now = new Date()
now.getFullYear() // 年
now.getMonth() // 月(0-11,注意+1)
now.getDate() // 日
now.getDay() // 星期(0-6,0=周日)
now.getHours() // 时
now.getMinutes() // 分
// JSON(数据交换格式)
JSON.stringify({ name: '张三', age: 18 }) // '{"name":"张三","age":18}'
JSON.parse('{"name":"张三","age":18}') // { name: '张三', age: 18 }
八、综合练习
练习1:学生成绩统计
let students = [
{ name: '张三', score: 85 },
{ name: '李四', score: 92 },
{ name: '王五', score: 78 }
]
// 计算平均分
let avg = students.reduce((sum, s) => sum + s.score, 0) / students.length
// 找最高分学生
let best = students.reduce((a, b) => a.score > b.score ? a : b)
// 所有人成绩+5分
students.forEach(s => s.score = Math.min(s.score + 5, 100))
练习2:随机生成验证码
function generateCode(length = 6) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let code = ''
for (let i = 0; i < length; i++) {
code += chars[Math.floor(Math.random() * chars.length)]
}
return code
}
console.log(generateCode()) // 如:'aB3kLm'
九、知识图谱
对象与内置对象
├── 对象
│ ├── 创建:字面量 {} / new Object()
│ ├── 访问:点语法 / 方括号语法
│ ├── 增删改查(CRUD)
│ ├── 遍历:for...in / Object.keys/values/entries
│ ├── 方法(函数作为属性)
│ └── this(指向调用对象,运行时确定)
├── Math 内置对象
│ ├── 取整:floor / ceil / round / trunc
│ ├── 其他:abs / max / min / pow / sqrt
│ └── 随机数:random(),配合 floor 取整范围
└── 引用类型
├── 赋值复制的是地址(不是值)
├── 多个变量可能指向同一对象
└── 函数传参也是传地址,会修改原对象
十、高频面试题
Q1:如何判断对象上是否有某个属性?
let obj = { name: '张三', age: 18 }
'name' in obj // true(包含原型链)
obj.hasOwnProperty('name') // true(只检查自身属性)
obj.name !== undefined // true(但如果值本身是 undefined 就失效)
Object.hasOwn(obj, 'name') // true(ES2022,推荐)
Q2:浅拷贝和深拷贝?
// 浅拷贝:只复制一层,嵌套对象仍然共享引用
let a = { x: 1, y: { z: 2 } }
let b = { ...a } // 展开运算符(浅拷贝)
let c = Object.assign({}, a) // Object.assign(浅拷贝)
b.x = 10 // 不影响 a.x
b.y.z = 99 // 影响 a.y.z!(共享引用)
// 深拷贝:完全独立的副本
let d = JSON.parse(JSON.stringify(a)) // 简单方法(有限制)
let e = structuredClone(a) // 现代方法(ES2022)
Q3: null 和 undefined 的区别?
null是一个表示"空对象"的特殊值,通常是程序员主动赋予的;undefined是变量未赋值时的默认状态。typeof null是'object'(历史 bug),typeof undefined是'undefined'。
⬅️ 上一篇:Day4 - 函数与作用域 ➡️ 下一篇:Web APIs Day1 - DOM操作基础