1、深入对象
1.1 创建对象三种方式
1.1.1 利用对象字面量创建对象
1.1.2 利用new Object创建对象
1.1.3 利用构造函数创建对象
1.2 构造函数
构造函数:是一种特殊的函数,主要用来初始化对象
使用场景:常规的{...}语法允许创建一个对象。比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一遍,此时可以通过构造函数来快速创建多个类似的对象。
注意构造函数在技术上是常规函数
不过有两个约定:
- 它们的命名以大写字母开头
- 它们只能由“new”操作符来执行
1.2.1 创建构造函数
语法:大写字母开头的函数
说明:
- 使用new关键字调用函数的行为被称为实例化
- 实例化构造函数时没有参数时可以省略()
- 构造函数内部无需写return,返回值即为新创建的对象
- 构造函数内部的return返回的值无效,所以不要写return
- new Object() new Date() 也是实例化构造函数
1.2.2 练习 利用构造函数创建多个对象
需求:
①:写一个Goods构造函数
②:里面包含属性name商品名称 price价格 count 库存数量
③:实例化多个商品对象,并打印到控制台
<script>
function Goods(name,price,count){
this.name = name
this.price = price
this.count = count
}
const mi = new Goods('小米',1999,20)
console.log(mi)
const hw = new Goods('华为',3999,59)
console.log(hw)
const vi = new Goods('vivo',1888,100)
console.log(vi)
</script>
1.2.3 实例化执行过程
说明:
- 创建新的空对象
- 构造函数this指向新对象
- 执行构造函数代码,修改this,添加新的属性
- 返回新对象
1.3 实例成员&静态成员
1.3.1 实例成员
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
说明:
- 为构造函数传入参数,创建结构相同但值不同的对象
- 构造函数创建的实例对象彼此独立互不影响
1.3.2 静态成员
构造函数的属性和方法被称为静态成员(静态属性和静态方法)
说明:
- 静态成员只能构造函数来访问
- 静态方法中的this指向构造函数
比如:Date.now() Math.PI Math.random()
2、内置构造函数
在JavaScript中最主要的数据类型有6种:
基本数据类型:字符串、数值、布尔、undefined、null
引用类型:对象
特殊情况:
其实字符串、数值、布尔等基本类型也都有专门的构造函数,这些被称为包装类型。
JS中几乎所有的数据都可以基于构造函数创建。
引用类型
Object,Array,RegExp,Date等
包装类型
String,Number,Boolean等
2.1 Object
Object是内置的构造函数,用于创建普通对象。
推荐使用字面量方式声明对象,而不是Object构造函数。
2.1.1 三个常用静态方法
静态方法就是只有构造函数Object可以调用的。
(1)Object.keys
作用:Object.keys静态方法获取对象中所有属性(键)
语法:
注意:返回的是一个数组
(2)Object.values
作用:Object.values静态方法获取对象中所有属性值
语法:
注意:返回的是一个数组
(3)Object.assign
作用:Object.assign静态方法常用于对象拷贝
语法:
使用:经常使用的场景给对象添加属性
2.2 Array
Array是内置的构造函数,用于创建数组
创建数组建议使用字面量创建,不用Array构造函数创建
2.2.1 数组常见实例方法-核心方法
方法 | 作用 | 说明 |
forEach | 遍历数组 | 不返回数组,经常用于查找遍历数组元素 |
filter | 过滤数组 | 返回新数组,返回的是筛选满足条件的数组元素 |
map | 迭代数组 | 返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组 |
reduce | 累计器 | 返回累计处理的结果,经常用于求和等 |
作用:reduce返回累计处理的结果,经常用于求和等
基本语法:
参数:如果有起始值,则把初始值累加到里面
<script>
// 数组reduce方法
// arr.reduce(function(上一次值,当前值){},初始值)
const arr = [1,5,8]
// // 1.没有初始值
// const total = arr.reduce(function(prev,current){
// return prev + current
// })
// console.log(total)
// 2.有初始值
// const total = arr.reduce(function(prev,current){
// return prev + current
// },10)
// console.log(total)
// 3.箭头函数的写法
const total = arr.reduce((prev,current) => prev + current , 10)
console.log(total)
</script>
reduce执行过程:
- 如果没有起始值,则上一次值以数组的第一个数组元素的值
- 每一次循环,把返回值给做为下一次循环的上一次值
- 如果有起始值,则起始值做为上一次值
2.2.2 计算薪资案例
需求:
①:根据数据计算当月支出薪资
数据:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const arr = [{
name: '张三',
salary: 10000
}, {
name: '李四',
salary: 10000
}, {
name: '王五',
salary: 10000
},
]
// 计算薪资案例
// const total = arr.reduce((prev,current) => {
// return prev + current.salary
// },0)
// console.log(total)
// 上一次值 当前值 返回值(第一次遍历)
// 0 10000 10000
// 上一次值 当前值 返回值(第二次遍历)
// 10000 10000 20000
// 上一次值 当前值 返回值(第三次遍历)
// 20000 10000 30000
// 需求: 每个人涨薪30%,当月支出多少薪资
const total = arr.reduce((prev,current) => prev + current.salary * 1.3,0)
console.log(total)
// 上一次值 当前值 返回值(第一次遍历)
// 0 13000 13000
// 上一次值 当前值 返回值(第二次遍历)
// 13000 13000 26000
// 上一次值 当前值 返回值(第三次遍历)
// 26000 13000 390000
</script>
</body>
</html>
2.2.3 数组常见方法-其他方法
2.2.4 练习
需求:
const spec = {size:‘40cm*40cm',color:'黑色'}
请将size和color里面的值拼接为字符串之后,写到div标签里面,展示内容如下:
思路:获得所有的属性值,然后拼接字符串就可以了
①:获得所有属性值是:Object.values() 返回的是数组
②:拼接数组是join('') 这样就可以转换为字符串了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div></div>
<script>
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('/')
</script>
</body>
</html>
2.2.5 数组常见方法-伪数组转换伪真数组
静态方法 Array.from()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
// Array.from(lis) 把伪数组转换为真数组
const lis = document.querySelectorAll('ul li')
// console.log(lis)
// lis.pop() 报错
const liss = Array.from(lis)
liss.pop()
console.log(liss)
</script>
</body>
</html>
2.3 String
在JavaScript中的字符串、数值、布尔具有对象的使用特征,如具有属性和方法
之所以具有对象特征的原因是字符串、数值、布尔类型数据是JavaScript底层使用Object构造函数“包装”来的,被称为包装类型。
2.3.1 常见实例方法
2.3.2 练习
请将下面字符串渲染到准备好的p标签内部,结构必须如左下图所示,展示效果如右图所示:
const gift = '50g茶叶,清洗球'
思路:
- 把字符串拆分为数组,这样两个赠品就拆分开了 用split(',')
- 利用map遍历数组,同时把数组元素生成到span里面,并且返回
- 因为返回的是数组,所以需要转换为字符串,用join('')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const gift = '50g的茶叶,清洗球'
// 1.把字符串拆分为数组
// console.log(gift.split(','))
// 2.根据数组元素的个数,生成对应的span标签
// const arr = gitf.split(',').map(function(item){
// return `<span>【赠品】${item}</span> <br>`
// }).join('')
// // console.log(arr)
// document.querySelector('div').innerHTML = str
document.querySelector('div').innerHTML = gift.split(',').map(item => `<span>【赠品】${item}</span> <br>` ).join('')
</script>
</body>
</html>
2.4 Number
Number是内置的构造函数,用于创建数值
常用方法:
toFixed()设置保留小数位的长度
3、综合案例-购物车展示
需求:根据后台提供的数据,渲染购物车页面
分析业务模块:
①:渲染图片、标题、颜色、价格、赠品等数据
②:单价和小计模块
③:总价模块
把整体的结构直接生成然后渲染到大盒子.list里面
- 先利用map来遍历,有多少条数据,渲染多少相同商品
- 可以先写死的数据
- 注意map返回值是数组,我们需要用join转换为字符串
- 把返回的字符串赋值给list大盒子的innerHTML
- 里面更换各种数据,注意使用对象解构赋值
- 先更换不需要处理的数据、图片,商品名称,单价,数量
- 采取对象解构的方式
- 注意 单价要保留2位小数 489.00 toFixed(2)
- 更换数据-处理规格文字模块
- 获取每个对象里面的spec,上面对象解构添加spec
- 获得所有属性值是:Object.values() 返回的是数组
- 拼接数组是join('') 这样就可以转换位字符串了
- 更换数据-处理赠品 模块
- 获取每个对象里面的gift,上面对象解构添加gift
- 注意要判断是否有gif属性,没有的话不需要渲染,利用变成的字符串然后写到p.name里面
- 更换数据-处理小计模块
- 小计=单价*数量
- 小计名可以为:subTotal = price* count
- 注意保留2位小数
- 计算合计模块
- 求和用到数组reduce方法 累计器
- 根据数据里面的数量和单价累加和即可
- 注意reduce方法有2个参数,第一个是回调函数,第二个是初始值,这里写0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.list {
width: 990px;
margin: 100px auto 0;
}
.item {
padding: 15px;
transition: all .5s;
display: flex;
border-top: 1px solid #e4e4e4;
}
.item:nth-child(4n) {
margin-left: 0;
}
.item:hover {
cursor: pointer;
background-color: #f5f5f5;
}
.item img {
width: 80px;
height: 80px;
margin-right: 10px;
}
.item .name {
font-size: 18px;
margin-right: 10px;
color: #333;
flex: 2;
}
.item .name .tag {
display: block;
padding: 2px;
font-size: 12px;
color: #999;
}
.item .price,
.item .sub-total {
font-size: 18px;
color: firebrick;
flex: 1;
}
.item .price::before,
.item .sub-total::before,
.amount::before {
content: "¥";
font-size: 12px;
}
.item .spec {
flex: 2;
color: #888;
font-size: 14px;
}
.item .count {
flex: 1;
color: #aaa;
}
.total {
width: 990px;
margin: 0 auto;
display: flex;
justify-content: flex-end;
border-top: 1px solid #e4e4e4;
padding: 20px;
}
.total .amount {
font-size: 18px;
color: firebrick;
font-weight: bold;
margin-right: 50px;
}
</style>
</head>
<body>
<div class="list">
<!-- <div class="item">
<img src="https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg" alt="">
<p class="name">称心如意手摇咖啡磨豆机咖啡豆研磨机 <span class="tag">【赠品】10优惠券</span></p>
<p class="spec">白色/10寸</p>
<p class="price">289.90</p>
<p class="count">x2</p>
<p class="sub-total">579.80</p>
</div> -->
</div>
<div class="total">
<div>合计:<span class="amount">1000.00</span></div>
</div>
<script>
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) // 每一条对象
// 对象解构 item.price item.count
const { picture,name,count,price,spec,gift} = item
// 规格文字模块处理
const text = Object.values(spec).join('/')
// 计算小计模块 单价*数量 保留两位小数
// 注意精度问题,因为保留两位小数,所以乘以100 最后除以100
const subTotal = ((price * 100 * count)/100).toFixed(2)
// 处理赠品模块 '50g茶叶,清洗球'
const str = gift ? gift.split(',').map(item => `<span class="tag">【赠品】${item}</span>`).join(''): ''
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">${count}</p>
<p class="sub-total">${subTotal}</p>
</div>
`
}).join('')
// 3. 合计模块
const total = goodsList.reduce((prev,item) => prev + (item.price * 100 * item.count) / 100, 0)
console.log(total)
document.querySelector('.amount').innerHTML = total.toFixed(2)
</script>
</body>
</html>