目录
2.1.1 Object.keys 静态方法获取对象中所有属性(键)
2.2.2 Object.values 静态方法获取对象中所有属性值
2.2.3 Object. assign 静态方法常用于对象拷贝
2.3 String
1 深入对象
1.1创建对象三种方式
1.1.1 利用对象字面量创建对象[推荐]
const pig={
name:'佩奇',
age:6
}
console.log(pig)
1.1.2 利用 new Object 创建对象
//new object为内置构造函数
const pig = new Object({
name: '佩奇',
age: 6
})
console.log(pig)
1.1.3. 利用构造函数创建对象
function Pig(name,gender,age){
this.name=name
this.gender=gender
this.age=age
}
const pq=new Pig('佩奇','女',6)
const qz=new Pig('乔治','男',8)
console.log(pq)
console.log(qz)
1.2 构造函数
构造函数 :是一种特殊的函数,主要用来初始化对象
使用场景:常规的 {...} 语法允许创建一个对象。比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一 遍,此时可以通过构造函数来快速创建多个类似的对象。
构造函数在技术上是常规函数。
不过有两个约定(不是规定):
1. 它们的命名以大写字母开头。
- 如Object, Date
2. 它们只能由 "new" 操作符来执行
- 不加new直接调用会undefined,因为函数中未写返回值return
说明:
1. 使用 new 关键字调用函数的行为被称为实例化
2. 实例化构造函数时没有参数时可以省略 ()
3.返回值
- 构造函数内部无需写return,返回值即为新创建的对象
- 构造函数内部的 return 返回的简单类型值无效,引用类型的值会被返回。所以不要写return
4. new Object() new Date() 也是实例化构造函 数
练习 • 利用构造函数创建多个对象
需求: ①:写一个Goods构造函数 ②:里面包含属性 name 商品名称 price 价格 count 库存数量 ③:实例化多个商品对象,并打印到控制台,例如
小米 1999 20
华为 3999 59
vivo 1888 100
function Goods(name, price, count) {
this.name = name
this.price = price
this.count = count
}
const xm = new Goods('小米', 1999, 20)
const hw = new Goods('华为', 3999, 59)
const vv = new Goods('vivo', 1888, 100)
console.log(xm);
console.log(hw);
console.log(vv);
- new实例化执行过程
new的过程
1 创建一个新对象
2 将this与新对象绑定
3 将函数内部属性挨个赋值给this(新对象)
4 return新对象(内部操作,无需单写)
1.3 实例成员&静态成员
目标:能够说出什么是实例成员和静态成员
实例成员:通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。
说明:
1. 实例对象的属性和方法即为实例成员
2. 为构造函数传入参数,动态创建结构相同但值不同的对象
3. 构造函数创建的实例对象彼此独立互不影响。(不同内存地址)
静态成员:构造函数的属性和方法被称为静态成员
说明:
1. 构造函数的属性和方法被称为静态成员
2. 一般公共特征的属性或方法静态成员设置为静态成员
3. 静态成员方法中的 this 指向构造函数本身
2 内置构造函数
在 JavaScript 中最主要的数据类型有 6 种:
基本数据类型: 字符串、数值、布尔、undefined、null
引用类型: 对象
但其实,基本数据类型在JavaScript底层也是由Object构造函数来调用的, 这些我们称为包装类型。
- JS中几乎所有的数据都可以基于构造函数创建。即数据可分为:
引用类型 : Object,Array,RegExp(正则表达式),Date 等 ( 得自己构造 )
包装类型 : String,Number,Boolean 等 ( 内置 )
2.1 Object
学习三个常用静态方法(静态方法就是只有构造函数Object可以调用的)
- 以往想要获取对象里的属性和值怎么做? ( for in )
const o = { name: '张三', age: 333 } for (let k in o) { console.log(k); // 属性: name age console.log(o[k]); // 值: 张三 333 }
2.1.1 Object.keys 静态方法获取对象中所有属性(键)
let arr=Object.keys(o)
console.log(arr) // ['name','age']
注意: 返回的是一个数组, 可利用Object.keys判断对象是否为空
console.log(Object.keys(o).length === 0) //false
2.2.2 Object.values 静态方法获取对象中所有属性值
返回结果同样是数组
console.log(Object.values(o)); //['张三','333']
2.2.3 Object. assign 静态方法常用于对象拷贝
const pig = { name: '佩奇', age: 18 }
const piig = {gender:'男'}
Object.assign(piig, pig) // b拷给a,而非覆盖a
console.log(piig) // {gender: '男', name: '佩奇', age: 18}
常用于给对象新增属性
const person={name:'张三',age:18}
Object.assign(person,{gender:'男'}) // {gender: '男', name: '佩奇', age: 18}
之前使用的 let piig=pig 不仅会覆盖piig的全部属性, 还会使二者共享一个内存地址, 使数据相互污染
2.2 Array
Array 是内置的构造函数,用于创建数组
// 此时arr为实例对象(new)
const arr = new Array(1, 2, 3)
console.log(arr) //[1,2,3]
创建数组建议使用字面量创建,不用 Array构造函数创建
2.2.1 数组常见实例方法-核心方法
(1) forEach: 遍历数组, 没有返回值,常用于打印数据, 拼接数据
注意: 参数当前数组元素是必须要写的, 索引号可选。
(2) map: 遍历数组, 处理数组中的每个值, 返回新数组 (比 forEach好用)
// map里面只有一个参数(回调函数),回调函数中又有三个形参
[3, 6, 7, 4, 1, 2].map(function (item, index, o) {
// 形参可替换(看位置不看名称),不用可不写
// 第一个形参为当前元素,每个元素,习惯用item
// 第二个形参为当前元素的索引值,习惯用index
// 第三个形参为数组本身
console.log(item, index, o)
})
// 求各元素乘方 :
const pow = [1, 3, 4, 5, 8, 9].map(function (item, index, o) {
return Math.pow(item, 3)
})
console.log(pow); // [1, 27, 64, 125, 512, 729]
(3) filter : 遍历数组,有返回值, 常用于数据筛选, 把符合条件的数组筛选(返回)出来
返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组
参数:currentValue 必须写, index 可选
因为返回新数组,所以不会影响原数组
(4) reduce
作用:reduce 返回函数累计处理的结果,经常用于求和等
reduce有两个参数: 回调函数(callback)+起始值
- function
- 起始值
1. 如果有起始值,则以起始值为准开始累计, 累计值 = 起始值
2. 如果没有起始值, 则累计值以数组的第一个数组元素作为起始值开始累计
3. 后面每次遍历就会将后面的数组元素 累计到 累计值 里面 (类似求和里面的 sum )
let arr = [1, 2, 3, 4]
const total = arr.reduce(function (prev, item, i, arr) {
console.log(arr) //始终为 [1, 2, 3, 4]
return prev + item
}, 0)
- 使用场景:求和运算:
练习 • 员工涨薪计算成本
需求: ①:给员工每人涨薪 30% ②:然后计算需要多支出的费用 数据:
// 原始数据
const arr = [{
name: '张三',
salary: 10000
}, {
name: '李四',
salary: 20000
}, {
name: '王五',
salary: 30000
},
]
// 计算
const add = arr.reduce((prev, item) => prev + item.salary * 0.3, 0)
console.log(add);
(5) join数组拼接字符串
const string = [3, 6, 7, 4, 1, 2].join('+')
// join参数写分隔符如+-&等等,如不需''即可
console.log(string)
二 其他方法
(6) find + findIndex
// 2 find, 也能遍历
//与filter的区别: filter返回数组,find返回一个值
const arr = [20, 30, 90, 80, 55]
console.log(arr.find(item => item > 50)); //90
console.log(arr.find(item => item > 100)); //undefined
// 3 findIndex 查找第一个对应元素的索引值
const arr2 = [20, 30, 90, 80, 55]
console.log(arr.findIndex(item => item > 50)); //2
console.log(arr.findIndex(item => item > 100)); //-1
(7) every + some
const groupScore = [50, 60, 70, 80, 90]
// 4 every 检测所有元素
console.log(groupScore.every(item => item > 70)); // false
console.log(groupScore.every(item => item > 20)); // true
// 5 some 检测是否存在符合条件的元素
console.log(groupScore.some(item => item > 70)); // true
console.log(groupScore.some(item => item > 20)); // true
练习 • 请完成以下需求
const spec = { size: '40cm*40cm' , color: '黑色'}
请将size和color里面的值拼接为字符串之后,写到div标签里面,展示内容如下:
// // 法一: 直观, 但是属性不固定,不普适
// const spec = { size: '40cm*40cm', color: '黑色' }
// const { size, color } = spec
// const string = [size, color].join('/')
// document.body.innerHTML = `<div>${string}</div>` // 40cm*40cm/黑色
// 法二: Object.values 可获取所有属性值
const spec = { size: '40cm*40cm', color: '黑色' }
const arr = Object.values(spec)
document.body.innerHTML = `<div>${arr.join('/')}</div>` // 40cm*40cm/黑色
2.2.2 数组静态方法- 伪数组转换为真数组
静态方法 Array.from()
function reader() {
const result = Array.from(arguments).reduce((prev, item) => prev + item)
console.log(result);
}
reader(1, 2, 3, 4)
2.3 String
练习 • 显示赠品练习
场景:
需求:
请将下面字符串渲染到准备好的 p标签内部,结构必须如左下图所示,展示效果如右图所示: const gift = '50g茶叶,清洗球'
//思路:字符串→数组→处理数组→拼为字符串→渲染
// 1 原字符串
const gift = '50g茶叶,清洗球' // 字符串
// 2 分割字符串为数组
const arr = gift.split(',')
// console.log(arr);
// 3 处理数组(遍历)
const newArr = arr.map(item => `<span>【赠品】${item}</span><br>`)
// console.log(newArr);
// ['<span>【赠品】50g茶叶</span><br>', '<span>【赠品】清洗球</span><br>']
// 4 连接字符串并渲染
document.body.innerHTML = `<p>${newArr.join('')}</p>`
// 简写
const gift2 = '50g茶叶,清洗球' // 字符串
document.body.innerHTML =
`<p>${gift2.split(',').map(item => `<span>【赠品】${item}</span><br>`).join('')}</p>`
2.4 Number
常用方法:toFixed() 设置保留小数位的长度
const num=12.345
console.log(num.toFixed(2)); // 12.35
const num2=12.385 //四舍六入
console.log(num2.toFixed(2)); // 12.38
注意: 小数处理方式为四舍六入(银行家算法) 详看: js toFixed 四舍五入问题 - 掘金 (juejin.cn)
弥补方法:
3 综合案例- 购物车展示
需求: 根据后台提供的数据,渲染购物车页面
分析业务模块: ①:渲染图片、标题、颜色、赠品等数据 ②:单价和小计模块 ③:总价模块
// 1 通过遍历,生成代表每个商品的标签字符串 (可以先不修改具体数据,看看整体效果会更直观)
const htmlStr = goodsList.map(item => {
// 4 批量解构
const { name, price, picture, count, spec, gift } = item
// 5 处理spec 对象→字符串
const newSpec = Object.values(spec).join('/') // 数组连接成字符串
// 6 处理赠品(先判断有无) 和先命名再判断赋值效果一致
const newGift = gift ? gift.split(',').map(item => `【赠品】${item}<br>`).join('') : ''
// 总价
const subTotal = (price.toFixed(2) * 100 * count) / 100 //单项
// const total = (total * 100 + subTotal * 100) / 100 //总计 (用reduce累加比较好)
// 3 替换数据
return `
<div class="item">
<img src="${picture}" alt="">
<p class="name">${name}
<span class="tag">${newGift}</span>
</p>
<p class="spec">${newSpec}</p>
<p class="price">${price.toFixed(2)}</p>
<p class="count">x${count}</p>
<p class="sub-total">${subTotal.toFixed(2)}</p>
</div>
`
// 注:浮点算法小数存在精度问题 (0.1+0.2!==0.3) → (0.1*10+0.2*10)/10===0.3 (即先转化为整数,就不存在小数的精度问题了)
})
// 2 数组转成字符串赋值给.list
document.querySelector('.list').innerHTML = htmlStr.join('')
// 7 总计 // 参数传入即解构 const { price, count } = item
const total = goodsList.reduce((prev, { price, count }) => prev + (price * 100 * count) / 100, 0)
document.querySelector('.total .amount').innerHTML = total.toFixed(2)