掌握基于构造函数创建对象,理解实例化过程,掌握对象数组字符数字等类型的常见属性和方法,便捷完成功能。
深入对象
创建对象三种方式
1. 利用对象字面量创建对象
2. 利用 new Object 创建对象
const obj = new Object()
obj.uname = '霍欣标'
console.log(obj)
// 简约的写法
// const obj = new Object({ uname: '霍欣标' })
// console.log(obj)
3. 利用构造函数创建对象
构造函数
构造函数是一种特殊的函数,主要用来初始化对象。
使用场景:常规的{...}
语法允许创建一个对象。比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一遍,此时可以通过构造函数来快速创建多个类似的对象。
构造函数在技术上是常规函数,有两个约定:
1. 它们的命名以大写字母开头。
2. 它们只能由new
操作符来执行。
- 使用
new
关键字调用函数的行为被称为实例化,实例化就是变成一个对象 - 实例化构造函数时没有参数时可以省略
()
- 构造函数内部无需写
return
,返回值即为新创建的对象 - 构造函数内部的
return
返回的值无效,所以不要写return
new Object()
new Date()
也是实例化构造函数
// 构造函数里面想声明一个变量,可以直接用this
function Pink(item) {
this.arr = 10
console.log(this.arr)
}
new Pink() // 10
// 创建一个猪 构造函数
function Pig(uname, age) {
// 新的空对象{}.对象的属性 = 形参
this.uname = uname
this.age = age
}
const p = new Pig('佩奇', 6)
console.log(p) // Pig { uname: '佩奇', age: 6 }
// console.log(new Pig('佩奇', 6)) // Pig {uname: '佩奇', age: 6}
// console.log(new Pig('乔治', 3)) //Pig { uname: '乔治', age: 3 }
练习:构造函数创建多个对象
function Goods(name, price, count) {
this.name = name
this.price = price
this.count = count
}
const mi = new Goods('小米', 1999, 20)
console.log(mi) // Goods {name: '小米', price: 1999, count: 20}
const hw = new Goods('华为', 3999, 50)
console.log(hw) // Goods {name: '华为', price: 3999, count: 50}
// 如同时间初始化,系统创建的构建函数,现在我们可以自己创建
const date = new Date('2024-4-8')
console.log(date) // Mon Apr 08 2024 00:00:00 GMT+0800 (中国标准时间)
实例化执行过程
- 创建新的空对象
- 构造函数
this
指向新对象 - 执行构造函数代码,修改
this
,添加新的属性 - 返回新对象
实例成员
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
- 为构造函数传入参数,创建结构相同但值不同的对象
- 构造函数创建的实例对象彼此独立互不影响
// 实例成员和静态成员
// 实例成员:实例对象上的属性和方法属于实例成员
function Pig(name) {
this.name = name
}
const peiqi = new Pig('佩奇')
const qiaozhi = new Pig('乔治')
peiqi.name = '小猪佩奇' // 实例属性 (实例成员)
peiqi.sayHi = () => { // 实例方法 (实例成员)
console.log('hi~~~')
}
console.log(peiqi === qiaozhi) // false
console.log(peiqi) // Pig {name: '小猪佩奇', sayHi: ƒ}
console.log(qiaozhi) // Pig {name: '乔治'}
静态成员
构造函数的属性和方法被称为静态成员(静态属性和静态方法)。比如Date.now()
Math.Pl
Math.random()
- 静态成员只能构造函数来访问
- 静态方法中的this指向构造函数
// 静态成员 :构造函数上的属性和方法称为静态成员
function Pig(name) {
this.name = name
}
Pig.eyes = 2 // 静态属性
console.log(Pig.eyes) // 2
Pig.sayHi = function () { // 静态方法
console.log(this) // ƒ Pig(name) {this.name = name}
console.log('学到就要教人') // 学到就要教人
}
Pig.sayHi()
实例对象的属性和方法即实例成员,实例对象相互独立,实例成员当前实例对象使用。
内置构造函数
在JavaScript中最主要的数据类型有六种:基本数据类型——字符串
数值
布尔
undefined
null
; 引用类型——对象,但是,我们会发现有些特殊情况:
其实字符串、数值、布尔、等基本类型也都有专门的构造函数,这些我们称为包装类型。JS中几乎所有的数据都可以基于构成函数创建。
const str = '欣标'
console.log(str.length) // 2
const num = 12
console.log(num.toFixed(2)) // 12.00
// 等同于下面(底层完成) 内部执行:把简单数据类型包装为了引用数据类型
// 1.普通类型实例化,把欣标字符串包装成一个对象,然后就可以调用方法
const str = new String('欣标')
Object
引用数据类型:Object
Array
RegExp
Date
等。
包装数据类型:String
Number
Boolean
等。
Object 是内置的构造函数,用于创建普通对象。推荐使用字面量方式声明对象,而不是Object
构造函数
学习三个常用静态方法(静态方法就是只有构造函数Object
可以调用的)
经常使用的场景给对象添加属性
Object.keys
静态方法获取对象中所有属性(键)Object.values
静态方法获取对象中所有值Object.assign
静态方法常用于对象拷贝
const o = { uname: 'xinbiao', age: 18 }
// 1. 获得所有的属性名
console.log(Object.keys(o)) // 返回一个数组 ['uname', 'age']
// 2. 获得所有的属性值
console.log(Object.values(o)) //返回一个数组 ['xinbiao', 18]
// 3. 对象拷贝
const oo = {}
// 对象方法(拷贝位置,拷贝数据)
Object.assign(oo, o)
console.log(oo) // {uname: 'xinbiao', age: 18}
// 使用的场景给对象添加属性
Object.assign(o, { gender: '男' })
console.log(o) // { uname: 'xinbiao', age: 18, gender: '男' }
Array
Array
是内置的构造函数,用于创建数组,创建数组建议使用字面量创建,不用Array
构造函数创建
数组常见核心实例方法
方法 | 作用 | 说明 |
forEach |
遍历数组 | 不返回数组,经常用于查找遍历数组元素 |
filter |
过滤数组 | 返回新数组,返回的是筛选满足条件的数组元素 |
map |
迭代数组 | 返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组 |
reduce |
累计器 | 返回累计处理的结果,经常用于求和等 |
reduce
返回累计处理的结果,经常用于求和等。如果有起始值,则把初始值累加到里面。
// 数组reduce 方法
const arr = [1, 2, 3, 4]
// 1.没有初始值
// arr.reduce(function(上一次值,当前值){},初始值)
const total = arr.reduce(function (prev, current) {
return prev + current
})
console.log(total) // 10
// 2.有初始值
const total = arr.reduce(function (prev, current) {
return prev + current
}, 10) // 初始值(对应上一次值)是10 + prev + current
console.log(total) // 20
// 3.箭头函数
const total = arr.reduce((prev, current) => prev + current, 10)
console.log(total) // 20
reduce执行过程
- 如果没有起始值,则上一次值以数组的第一个数组元素的值
- 每一次循环,把返回值给做为下一次循环的上一次值
- 如果有起始值,则起始值做为上一次值
// 没有初始值
const arr = [1, 3, 8]
arr.reduce((prev, current) => prev + current)
// 上一次值 当前值 返回值(第一次循环)
// 1 3 4
// 上一次值 当前值 返回值(第二次循环)
// 4 8 12
// 有初始值
const arr = [1, 3, 8]
arr.reduce((prev, current) => prev + current, 10)
// 上一次值 当前值 返回值(第一次循环)
// 10 1 11
// 上一次值 当前值 返回值(第二次循环)
// 11 3 13
// 上一次值 当前值 返回值(第三次循环)
// 13 8 21
练习:计算薪资
根据数据计算当月支出薪资
当数据遇到[{ }]
数组包对象的时候,起始值一定不能省,初始值可以为0
const arr = [{
name: '张三',
salary: 10000
}, {
name: '李四',
salary: 10000
}, {
name: '王五',
salary: 20000
},
]
// 1. 需求:计算薪资案例
// 来声明常量 = arr.reduce(( 数组 , 对象 ))
const total = arr.reduce((prev, current) => {
console.log(prev)
return prev + current.salary // 对象.价格
}, 0) // [{ }]初始值千万不能省
console.log(total) // 40000
// 2. 需求:每个人涨新30%,当月支出多少新资
const total = arr.reduce((prev, current) => prev + current.salary * 1.3, 0)
console.log(total) // 52000
数组常见其他实例方法
实例方法 | 说明 |
join |
数组元素拼接为字符串,返回字符串 |
find |
查找元素,返回符合测试条件的第一个数组元素值,若没有符合条件的则返回undefined |
every |
检测数组所有元素是否都符合指定条件,若所有元素都通过检测返回true,否则返回false |
some |
检测数组中的元素是否满足指定条件,若数组中有元素满足条件返回true,否则返回 false |
concat |
合并两个数组,返回生成新数组 |
sort |
对原数组单元值排序 |
splice |
删除或替换原数组单元 |
reverse |
反转数组 |
findIndex |
查找元素的索引值 |
更多数组方法:mdn web docs Array
find 数组查找
数组套对象的数据,查找某一个数组对象值并返回这个对象。
// 查找元素
// const arr = ['red', 'blue', 'green']
// const re = arr.find(function (item) {
// return item === 'blue'
// })
// console.log(re) // blue
const arr = [
{
name: '小米',
print: 1999
},
{
name: '华为',
print: 3999
},
]
// 找小米 把这个对象,并且返回这个对象
const mi = arr.find(function (item) {
// console.log(item) // 数组元素
// console.log(item.name) // 数组元素里 name
// console.log(11) // 循环查找
return item.name === '小米' // 数组元素.name === 小米 就返回小米这个对象
})
console.log(mi) // {name: '小米', print: 1999}
// 简化箭头函数
const mi = arr.find(item => item.name === '小米')
console.log(mi) // {name: '小米', print: 1999}
eveny检查数组每一条数据
// every每一个是否都符合条件,如果都符合返回true,否则返回false
const arr = [10, 20, 30]
const flag = arr.every(item => item >= 10)
console.log(flag) // true
const arr1 = [9, 20, 30]
const flag1 = arr1.every(item => item >= 10)
console.log(flag1) // false
some检查符合一个值
// some方法数组中只有一个值符合条件,如果符合返回true,否则返回false
const arr2 = [3, 5, 30]
const flag = arr2.some(item => item >= 10)
console.log(flag) // true
练习:选购界面的数据处理
const spec = { size: '40cm*40cm', color: '黑色' }
将size
和color
里面的值拼接为字符串之后,写到div
标签里面,展示内容如:40cm*40cm/黑色
思路:获得所有的属性值,然后拼接字符串就可以了
- 获得所有属性值是:
Object.values()
返回的是数组 - 拼接数组是
join("")
这样就可以转换为字符串了
const spec = { size: '40cm*40cm', color: '黑色' }
// 1. 所有的属性值回去过来 数组
// console.log(Object.values(spec))
// 2. 转换为字符串 数组join('/') 把数组根据分隔符转换为字符串
// console.log(Object.values(spec).join('/'))
document.querySelector('div').innerHTML = Object.values(spec).join('/')
数组方法:伪数组转换为真数组
如果提示控制台Uncaught TypeError: lis.pop is not a function
,这说明lis
不是一个真数组。
NodeList
是伪数组
// Array.from 把伪数组转换为真数组
const lis = document.querySelectorAll('ul li')
// console.log(lis)
// lis.pop() 删除 报错
const liss = Array.from(lis) // 伪数组转换为真数组
liss.pop()
console.log(liss) // [li li]
String
在字符串中,一个中文汉字、一个英文字母、一个标点符号和一个空格都算是一个索引号,默认从0开始。
String常见实例方法
实例方法 | 使用说明 |
length | 用来获取字符串的度长(重点) |
split | 用来将字符串拆分成数组(重点) |
substring | 用于字符串截取(重点) |
startswith | 检测是否以某字符开头(重点) |
includes | 判断一个字符串是否包含在另一个字符串中,根据情况返回true 或false (重点) |
toUpperCase | 用于将字母转换成大写 |
toLowerCase | 用于将就转换成小写 |
indexOf | 检测是否包含某字符 |
endswith | 检测是否以某字符结尾 |
replace | 用于替换字符串,支持正则匹配 |
match | 用于查找字符串,支持正则匹配 |
split字符串转换数组
// 把字符串转换为数组, 与join相反
const str = 'pink,red'
const arr = str.split(',')
console.log(arr) // ['pink', 'red']
const str1 = '2024-4-8'
const arr1 = str1.split('-')
console.log(arr1) // ['2024', '4', '8']
const str3 = '180cm/58kg/黑色'
const arr3 = str3.split('/')
console.log(arr3) // ['180cm', '58kg', '黑色']
substring字符串截取
需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母
// 字符串截取 substring((开始索引号,结束索引号))
// 如果省略索引号,则取到最后
// 结束的索引号不包含截取的部分
const str = '今天又要去上班了'
console.log(str.substring(5)) // 上班了
console.log(str.substring(5, 7)) // 上班
startswith检测某字符开头
startswith
来判断当前字符串是否以另外一个给定的子字符串开头,并根据判断返回true
或false
// startsWith 判断是不是以某个字符开头
const str = 'xinbiao 今天又要去上班了'
console.log(str.startsWith('xinbiao')) // true
console.log(str.startsWith('xin')) // true
console.log(str.startsWith('欣标')) // false
endsWith检测某字符结束
// endsWith 判断是不是以某个字符结尾
const str = '欣标今天又要去上班'
console.log(str.endsWith('上班')) // true
console.log(str.endsWith('要去')) // false
includes检测字符串包含
用于判断一个字符串是否包含在另一个字符串中,根据情况返回true
或false
includes
是区分大小写
// includes 字符串是否包含检索词
const str = '我是霍欣标的小艺'
console.log(str.includes('霍欣标')) // true
console.log(str.includes('霍欣标', 2)) // true
console.log(str.includes('霍欣标', 3)) // false
练习:显示赠品
字符串渲染到准备好的p
标签内部,结构必须如左下图所示,展示效果如引用所示:
【赠品】50g茶叶
【赠品】清洗球
- 把字符串拆分为数组,这样两个赠品就拆分开了,用
split
- 利用
map
遍历数组,同时把数组元素生成到span
里面,并且返回 - 因为返回的是数组,所以需要 转换为字符串,用
join
const gift = '50g的茶叶,清洗球'
// 1. 把字符串拆分为数组
// console.log(gift.split(',')) // ['50g的茶叶', '清洗球']
// 2. 根据数组元素的个数,生成对应span标签
// const str = gift.split(',').map(function (item) {
// return `<span>【赠品】 ${item}</span> <br>`
// }).join('')
// console.log(str)
// document.querySelector('div').innerHTML = str
// 简化语法
document.querySelector('div').innerHTML = gift.split(',').map(item => `<span>【赠品】 ${item}</span> <br>`).join('')
Number
toFixed保留小数位
Number
是内置的构造函数,用于创建数值。
常用方法:toFixed()
设置保留小数位的长度,保留两位小数,四舍五入。
const num = 10.923
console.log(num.toFixed()) // 11
console.log(num.toFixed(1)) // 10.9
console.log(num.toFixed(2)) // 10.92
const num1 = 10
console.log(num1.toFixed()) // 10
console.log(num1.toFixed(1)) // 10.0
console.log(num1.toFixed(2)) // 10.00
转换为字符串
const num = 10
// 强制转换
console.log(String(num)) // 10
// 方法转换
console.log(num.toString()) // 10
Element.remove()
Element
是最通用的基类,Document
中的所有元素对象(即表示元素的对象)都继承自它。它只具有各种元素共有的方法和属性。更具体的类则继承自 Element
。
Element.remove()
方法,把对象从它所属的 DOM 树中删除。 Demo
const div = document.querySelector('div')
div.addEventListener('click', function () {
div.remove()
})
综合案例:购物车展示
分析业务模块:Demo
- 根据数据渲染页面
- 先利用
map
来遍历,有多少条数据,渲染多少相同商品 - 注意
map
返回值是数组,我们需要用join
转换为字符串 - 把返回的字符串 赋值 给
list
大盒子的innerHTML
- 先利用
- 更换数据
- 2.1 更换不需要处理的数据,图片,商品名称,单价,数量
- 采取对象解构的方式
- 注意单价要保留2位小数,489.00
toFixed(2)
- 2.2 更换规格文字模块
- 获取每个对象里面的
spec
,上面对象解构添加spec
- 获得所有属性值是
Object.values()
返回的是数组 - 拼接数组是
join('')
这样就可以转换为字符串了
- 获取每个对象里面的
- 2.3 更换赠品模块
- 获取 每个对象里面的
gift
,上面对象解构添加gift
- 思路:
- 把字符串拆分为数组,这样两个赠品就拆分开了用
split('')
方法 - 利用map遍历数组,同时把数组元素生成到span里面,并且返回
- 因为返回的是数组,所以需要 转换为字符串,用
join('')
方法
- 把字符串拆分为数组,这样两个赠品就拆分开了用
- 注意判断是否有
gif
属性,没有的话不需要渲染利用变成的字符串然后写到p.name
里面
- 获取 每个对象里面的
- 2.1 更换不需要处理的数据,图片,商品名称,单价,数量
- 总价模块
- 更换小计模块
- 小计 = 单价 * 数量
- 小计名可以为
subTotal = price * count
- 注意保留2位小数
- 小数计算精度问题,经常转换为整数:
(0.1 * 100 + 0.2 * 100) /100 === 0.3
- 更换合计模块
- 求和用到数组
reduce
方法累计器 - 根据数据里面的数量和单价累加和即可
- 注意
reduce
方法有2个参数,第一个是回调函数,第二个是初始值,这里写0
- 求和用到数组
- 更换小计模块
模版字符串虽好,但是格式一定要正规,不该有的空格不能多也不能少,不然就会显示异常
const goodsList = [
{
id: '4001172',
name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
price: 289.9,
picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
count: 2,
spec: { color: '白色' }
},
{
id: '4001009',
name: '竹制干泡茶盘正方形沥水茶台品茶盘',
price: 109.8,
picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
count: 3,
spec: { size: '40cm*40cm', color: '黑色' }
},
{
id: '4001874',
name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
price: 488,
picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
count: 1,
spec: { color: '青色', sum: '一大四小' }
},
{
id: '4001649',
name: '大师监制龙泉青瓷茶叶罐',
price: 139,
picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
count: 1,
spec: { size: '小号', color: '紫色' },
gift: '50g茶叶,清洗球,宝马,奔驰'
}
]
// 1. 根据数据渲染页面
document.querySelector('.list').innerHTML = goodsList.map(item => {
// console.log(item) // 每一条对象
// 对象解构
const { picture, name, count, price, spec, gift } = item
// 2.2 更换规格文字模块
const text = Object.values(spec).join('/')
// 2.3 处理赠品模块
const str = gift ? gift.split(',').map(item => `<span class="tag">【赠品】${item}</span>`).join('') : ''
// 3.计算小计模块 单价 * 数量
// 注意精度问题,因为保留两位小数,所以乘以100 最后除以100
const sbuTotal = ((price * 100 * count) / 100).toFixed(2)
return `
<div class="item">
<img src=${picture} alt="">
<p class="name">${name} ${str}</p>
<p class="spec">${text}</p>
<p class="price">${price.toFixed(2)}</p>
<p class="count">x${count}</p>
<p class="sub-total">${sbuTotal}</p>
</div>
`
}).join('')
// 3.合计模块
const total = goodsList.reduce((prev, item) => prev + (item.price * 100 * item.count) / 100, 0)
document.querySelector('.amount').innerHTML = total.toFixed(2)
原创文章,作者:霍欣标,如若转载,请注明出处:https://www.bigengwu.cn/xue/148.html