一、对象创建引发构造函数产生
1.1 创建对象三种方式:
- 利用对象字面量创建对象
const obj = {
name: '佩奇'
}
注:对象字面量的由来:即它是直接由字面形式(由源代码直接)创建出来的对象,而不是通过构造函数或者方法间接构成的,所以就叫做对象字面量。
- 利用 new Object 创建对象
// 两种添加属性的方式
// const obj = new Object()
// obj.uname = '哈哈哈哈'
// console.log(obj);
const obj = new Object({ uname: '哈哈哈哈' })
console.log(obj);
注:当使用Object时,实际上是调用了js内置的一个构造函数并且通过new关键字来创建一个新的对象。
3. 利用构造函数创建对象 往下看。。。。。
1.2 构造函数
构造函数定义:就是一个函数,用来创建快速多个类似的对象,将多个对象的公共属性封装在一个函数里
注意:创建对象的时候首字母大写;使用函数创建对象通过new关键字操作符。
//创建一个猪猪 构造函数
function Pig (uname, age) {
this.unmae = uname
this.age = age
}
// 通过new关键字调用函数
// 实例化构造函数
// console.log(new Pig('佩奇', 6))
const p = new Pig('佩奇', 6)
console.log(p);
另外:同new Object()、 new Date() 一样都是实例化构造函数,js内置了Date、Object构造函数,然后通过new关键字实现实例化函数,最后实现实例化对象
const date = new Date('2021-3-4')
console.log(date);
function Goods (name, price, count) {
this.nam = name
this.price = price
this.count = count
}
const mi = new Goods('小米', 1999, 20)
console.log(mi)
const hw = new Goods('华为', 1999, 50)
console.log(hw)
总结:
1.new关键字调用函数的行为被称为实例化
2.构造函数无return,构造函数自动返回构建的新的对象。
什么时候需要return?就是函数比起输出结果,将返回结果给其他程序,然后程序使用这个结果做其他事情更重要的时候。这个具体见小编的 js——函数篇。
3.实例化构造函数时没有参数时可以省略 ()
实例化执行过程
①构造函数先调用,加上new,立刻创建一个空对象 ②this指向空对象
③执行构造函数代码,利用this,添加属性.(具体是通过形参传入实参, this指向新对象,新对象添加一个name属性
这样实参通过形参就传入到了对象中 生成了对象属性 对象也有了 属性也有了 ,构造函数就会自动返回一个新的对象 返回的新对象 由new Pig接收。)
④.返回新对象
1.3 实例成员 静态成员
实例成员
通过构造函数创建的对象称为实例对象;
实例对象中的属性和方法称为实例成员 (实例属性 实例方法)
下面举一个不含有参数的利用构造函数创建实例对象:
function Pig () {
this.name = '佩奇'
this.sayHi = function () {
console.log('你好')
}
}
const p = new Pig()
console.log(p.name)
p.sayHi()
注:
- 实例对象的属性和方法即为实例成员
- 为构造函数传入参数,动态创建结构相同但值不同的对象
- 构造函数创建的实例对象彼此独立互不影响
静态成员
构造函数的属性和方法被称为静态成员 静态成员只能构造函数访问。
function Person () {
// 省略实例成员
}
// 静态属性
Person.eyes = 2
Person.arms = 2
// 静态方法
Person.walk = function () {
console.log('人嗯呢')
console.log(this.eyes)
}
new Person()
console.log(Person.eyes)
console.log(Person.arms)
// 死记硬背:遇到方法一定要想到需要调用 并且不用打印调用 方法里面有结果的输出
// console.log(Person.walk);//错误
Person.walk()
说明:
- 构造函数的属性和方法被称为静态成员
- 一般公共特征的属性或方法静态成员设置为静态成员
- 静态成员方法中的 this 指向构造函数本身
二、内置构造函数
一切皆对象
我发现因为构造函数的存在,所以都可以new出来一个实例对象
主要的数据类型有6种:
基本数据类型:字符串、数值、布尔、undefined、null
引用数据类型:对象、数组等。
字符串.Length
// const str = 'pink'
// // 有属性
// console.log(str.length)
// const num = 12
// // 有方法
// console.log(num.toFixed(2));
// js底层完成 把简单数据类型包装成了引用数据类型
// const str = new String('pink')
为什么任何数据都有属性和方法?
原理:其实在js的底层 将字符串类似转化为了对象,也就存在了属性和方法
基本包装类型就是基本数据类型包装成了复杂数据类型
实字符串、数值、布尔、等基本类型也都有专门的构造函数,这些我们称为包装类型。
JS中几乎所有的数据都可以基于构成函数创建
包装类型
String,Number,Boolean 等基本数据类型
2.1 Object
Object 是内置的构造函数,用于创建普通对象。
使用 Object 创建对象
const aa = new Object({ uname: '哈哈', age: 18 })
console.log(aa);
三个常用静态方法(静态方法就是只有构造函数可以调用的,在这里是只有Object可以调用的)
const o = { uanme: 'pink', age: 18 }
// 1.Object.keys 静态方法获取对象中所有属性(键) 返回数组
console.log(Object.keys(o))
// 2.Object.values 静态方法获取对象中所有属性值 返回数组
console.log(Object.values(o))
// 3.Object. assign 静态方法常用于对象拷贝 经常使用的场景给对象添加属性
const oo = {}
Object.assign(oo, o)
console.log(oo)
// 通过Object给对象添加属性
Object.assign(o, { gender: '女' })
console.log(o)
console.log(Object.keys(o));
2.2 Array
Array 是内置的构造函数,用于创建数组
const arr = new Array(3, 5)
console.log(arr);
创建数组建议使用字面量创建,不用 Array构造函数创建
数组常见实例方法:
数组中的reduce方法:
这里不知道大家会不会有个问题,为什么function函数没有被调用呢,就能够返回值,这是因为数组中的reduce方法是js内置函数自定义的方法,不需要我们返回,由内部操作,我们只需要知道function被当做参数传入的时候是回调函数,最后返回的结果用一个变量来接收即可。
// 数组reduce方法 两个参数 回调函数 初始值
// arr.reduce(function (上一次值,当前值) { }, 初始值)
const arr = [1, 5, 7]
// 1.没有初始值
const total = arr.reduce(function (prev, current) {
return prev + current
})
console.log(total)
// 2.有初始值
const total1 = arr.reduce(function (prev, current) {
return prev + current
}, 10)
console.log(total1)
// 3.箭头函数表示
const total2 = arr.reduce((prev, current) => prev + current, 20)
console.log(total2);
forEach 遍历数组 不返回新数组 也就是不返回值 就想着,遍历数组,就跟for循环一样,什么时候还有返回值呢!
<script>
const arr = ['red', 'green', 'pink']
// item是必须要写的
// foreach就是纯遍历 加强版的for循环 适合于遍历数组对象
const result = arr.forEach(function (item, index) {
console.log(item)//每个数组元素
console.log(index)//索引号
})
console.log(result)//不返回值
</script>
filter 筛选数组 所以一定会返回一个新的数组 也就是有返回值
<script>
const arr = [10, 20, 30]
// const newArr = arr.filter(function (item, index) {
// // 也有用item和index
// // console.log(item)
// // console.log(index)
// return item >= 20
// })
// console.log(newArr);
// 写成箭头函数
const newArr = arr.filter(item => item >= 20)
console.log(newArr);
</script>
map 迭代数组 返回新数组
如果没有进行字符串拼接等操作,默认是直接迭代数组,返回一个新的数组,和forEach方法类似,一个返回数组一个不返回
<script>
const arr = ['red', 'blue', 'pink']
const newArr = arr.map(function (ele, index) {
return ele + '颜色'
})
console.log(newArr)
// 字符串是黑色的
console.log(JSON.stringify(newArr))
console.log(arr.join(''))
console.log(newArr.join('|'));
</script>
综合案例一:
需求一:
把尺码和颜色 拼成特定格式要隔开():
思路:获得所有属性值,然后拼接字符串即可
①获得所有属性值:Object.values()返回的是数组
②拼接数组join 这样就可以转换为字符串了
这里我们需要注意,因为我们要求薪资和,可是薪资在每个对象中,而对象又是在数组中,所以当我们直接使用数组进行reduce累计求和,需要注意里面的参数实际上是映射到了每一个对象上
// 对象数组
const arr = [{
name: '张三',
salary: 10000
}, {
name: '李四',
salary: 10000
}, {
name: '王五',
salary: 20000
},
]
// 映射上每一个对象
const total = arr.reduce((prev, current) => {
console.log(prev)
console.log(current)
})
有结果可知,有undefined,根据reduce的执行过程可知,当没有添加初始值时,prev执行数组的第一个元素,在本案例中,是第一个对象,所以就会输出第一个对象,但是current会输出第二个对象,但是因为reduce通过多次遍历元素,每一次循环遍历都会将元素加在一起,但是显然我们求得的元素使对象不可能求和,所以得到undefined,因为每一轮循环返回的值回作为新一轮的prev,所以prev会返回一个undefined,紧接着current会返回之前遍历数组元素的下一个元素。
所以我们现在要解决的是怎么拿到数组元素对象中salary薪资,可以通过对象.属性拿到 但是注意一定要写成prev和current.salary,以及添加初始值
// 对象数组
const arr = [{
name: '张三',
salary: 10000
}, {
name: '李四',
salary: 10000
}, {
name: '王五',
salary: 20000
},
]
const total = arr.reduce((prev, current) => {
// console.log(prev)
// 在数组对象中累加和 不写初始值 错误 prev.salary第一次迭代的时候拿到的是元素 在我们这个代码中是第一个数值 问题是第二次迭代的时候我们想要实现的是prev拿到的是第一次迭代的返回值,显然如果我们非要写prev.salary就拿不到第一次迭代的返回值接着就有问题了,所以这里我们就用到了初始值
// return prev.salary + current.salary
// return prev + current.salary
}, 0)
console.log(total)
const total1 = arr.reduce((prev, current) => prev + current.salary * 1.3, 0)
console.log(total1)
Array数组常见方法
// 单纯数组 对数组进行查找满足条件的元素
const arr = ['red', 'blue', 'green']
const re = arr.find(function (item) {
return item === 'blue'
})
console.log(re)
//数组对象
const arr1 = [
{
name: '小米',
price: 1999
}, {
name: '华为',
price: 2913
}
]
// find查找满足条件的元素 因为是数组对象 所以查找满足条件的对象 只筛选满足条件的第一个元素
const mi = arr1.find(function (item) {
console.log(item)
console.log(item.name)
return item.name === '小米'
})
// 筛选每一个元素
const arr2 = [10, 20, 30]
const flag = arr.every(item => item >= 20)
console.log(flag);
2.3 String
js底层也见了构造函数进行包装
String常见方法 split把字符串转换为数组
//1.split把字符串转换为数组 和join()相反
const str = 'pink,red'
const arr = str.split(',')
console.log(arr)
const str1 = '2022-4-8'
const arr1 = str1.split('-')
console.log(arr1)
//2. 字符串的截取 substring(开始的索引号[,结束的索引号])
// 2.1 如果省略结束的索引号 默认取到最后
// 2.2 结束的索引号不包含在想要截取的部分
const str = '今天很开心啊'
// 不包含截取
console.log(str.substring(3, 5))
// 3.startwith 判断是不是以某个字符开头
const str = 'pink老师上课中'
console.log(str.startsWith('ink'))
// 4.includes 判断某个字符是不是包含在一个字符串中 以及该字符的位置
// 从字符串中开始搜索哈哈哈哈的位置 也就是开始搜索的位置
const str = '我是pink老师'
console.log(str.includes('pink'))
console.log(str.includes('pink', 3));
基于字符串的小赠品案例;字符串转换为数组的而案例 并且使用join展示在页面上
// 两个小赠品放在了字符串中,我们需要将这两个赠以页面要求的格式放在页面上 并且是两行
// 思路:将字符串通过split转化为数组,利用map方法将数组进行遍历拿到两个元素并且以页面要求的格式返回 最后获取页面元素进行innerHTML
const gift = '50g的茶叶,清洗球'
// 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('')
toFixed()
// 方法 可以让数字制定保留的小数位数
const num = 10.928
console.log(num.toFixed(2))
const num1 = 10
console.log(num1.toFixed(2));
基于构造函数&数据常用函数综合案例
功能实现:购物车展示 包括渲染图片 标题 颜色 价格 赠品等数据
- 把整体的结构直接生成然后渲染到大盒子list里面
- 遍历并且返回值:map方法
- 最后计算总价模块求和:reduce方法
- 具体思路:
①map遍历数据 先写死数据 join转化为字符串 追加给list的innerHTML
②更换数据 先更换不需要处理的数据 图片 商品名称 单价 数量
对象结构的方式 单价保留两位小数
③更换数据——处理规格文字模块
获取每个对象里面的spec,上面对象解构添加spec
获得所有属性值 Object.values()返回的是数组
拼接数组是join(‘’)这样就可以转换为字符串了
④更换数据——处理赠品模块
获取每个对象里面的gift,上面对象解构添加gift
思路:把字符串拆分为数组,这样两个赠品就拆分开了 用split()
利用map遍历数组,同时把数组元素生成到span里面,并且返回
因为返回的是数组 所以需要转换为字符串 用join‘’()
注意要判断是否有gift属性 没有的话不需要渲染
利用变成的字符串然后写到p.name里面
<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茶叶,清洗球,宝马, 奔驰'
}
]
// 因为是数组对象 所以使用map遍历数组 有返回值
document.querySelector('.list').innerHTML = goodsList.map(item => {
// console.log(item)
// 通过对象解构拿到想要的属性
const { picture, name, count, price, spec, gift } = item
//规格文字模块
const text = Object.values(spec).join('/')
// 计算小计模块 单价*数量
const subTotal = ((price * 100 * count) / 100).toFixed(2)
//处理赠品模块
const str = gift ? gift.split(',').map(item => `<span class="tag">【赠品】10${item}</span>`).join('') : ''
//这里在返回页面的时候先返回一个死的数据 便于梳理思路
return `<div div class="item" >
<img src=${picture} alt="">
<p class="name">${name}<span class="tag">【赠品】10优惠券</span></p>
<p class="spec">${text}</p>
<p class="price">${price}</p>
<p class="count">x${count}</p>
<p class="sub-total">579.80</p>
</div> `
}).join('')
// 3.合计模块
const total = (goodsList.reduce((prev, item) => prev + (item.price * 100 * item.count) / 100, 0)).toFixed(2)
document.querySelector('.amount').innerHTML = total
</script>
三 、 完整代码
<!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) //每一条对象 四条数据 遍历了四次
const { picture, name, count, price, spec, gift } = item
// 规格文字模块
const text = Object.values(spec).join('/') //Object.values(spec)获取的是数组
// 计算小计模块 单价*数量
const subTotal = ((price * 100 * count) / 100).toFixed(2)
// 处理赠品模块
const str = gift ? gift.split(',').map(item => `<span class="tag">【赠品】10${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">x${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)).toFixed(2)
// console.log(total);
document.querySelector('.amount').innerHTML = total
</script>
</body>
</html>