单例模式
-
创建一个类, 这个类的一生只能有一个实例化对象
-
完成思路:
- 首先要有一个 class
- 在每次准备实例化这个 lei 之前, 先判断之前有没有对这个 lei 进行过实例化
- 如果进行过, 那么我们不在进行新的实例化, 而是拿到之前的 实例化对象
- 如果没有进行过, 那么我们这时候开始进行一个实例化
// 单例模式升级
class Dialog {
constructor() {
this.naem = "李四"
}
}
let flag = null
function fn() {
if (flag === null) {
flag = new Dialog()
}
return flag
}
//====================封装以后为下面的代码==============
const fn = (() => {
let flag = null
class Dialog {
constructor() {
this.text = "李四"
}
say(text) {
this.text = text
}
}
return function (text) {
if (flag === null) {
flag = new Dialog()
}
flag.say(text) //在这里直接调用实例化对象的方法
return flag
}
})()
const d1 = fn("d1的文本")
console.log(d1);
const d2 = fn("d2的文本")
console.log(d1);
const d3 = fn("d3的文本")
console.log(d3);
console.log(d1);
策略模式
- 只是为了解决代码中 过多的 if...else 嵌套的问题
// 计算一本书的价格
// 如果打八折是多少钱
// 如果打七折是多少钱
// 如果打六折是多少钱
const calcPrice = (() => {
// 1. 先创建一个数据, 存储我们的折扣以及对应的价格
const priceList = {
'80%': function (total) {
// return '0.8 * 总价'
return 0.8 * total
},
'70%': (total) => {
return 0.7 * total
},
'60%': total => 0.6 * total
}
// 2.0 返回一个函数, 这个函数能够帮助你计算价格
function inner(total, type) {
return priceList[type](total)
}
// JS 中 所有的 引用数据类型 能够当成 对象使用
// 2.1 添加折扣功能
inner.add = function (key, value) {
priceList[key] = value
}
// 2.2 删除折扣功能
inner.del = function (key) {
delete priceList[key]
// console.log(priceList)
}
// 2.3 获取所有折扣列表
inner.get = function () {
return priceList
}
return inner
})()
calcPrice.add('300-30', (total) => total - Math.floor(total / 300) * 30)
calcPrice.del('60%')
console.log(calcPrice.get())
发布订阅模式
- 去书店买书
- 去书店, 没有
- 留下联系方式, 将来书店会根据联系方式, 通知你 书有了
- 有了书之后, 去书店
- 方案1:
- {
- 本的名字1: [联系人1, 联系人2, 联系人3, .....]
- 本的名字2: [联系人1, 联系人2, 联系人3, .....]
- }
- 方案2:
- [
- {
- book: 书名1,
- num: 联系方式1
- },
- {
- book: 书名1,
- num: 联系方式2
- },
- {
- book: 书名1,
- num: 联系方式3
- },
- {
- book: 书名2,
- num: 联系方式4
- }
- {
- ]
class cs {
constructor() {
this.name = '张三' // 售货员的名字, 有没有这个属性 不重要
this.message = {} // 按照方案一的思路去存储
}
/**
* {
* 书本1: [联系人1, 联系人2, 联系人3, ....]
* 书本2: [联系人1, 联系人2, 联系人3, ....]
* }
*/
// 给书本加入联系人
add(bookName, user) {
// this.message[bookName] = [user]
// 调用当前方法, 能够预定一个书本 (只是留下联系方式)
if (this.message[bookName] === undefined) { this.message[bookName] = [] }
this.message[bookName].push(user)
}
// 给书本加入联系人
del(bookName, user) {
// 调用当前方法, 能够取消预订一个书本 (把联系方式 删掉)
this.message[bookName].forEach((item, index) => {
if (item === user) {
delete this.message[bookName][index]
}
})
}
tz(bookName) {
this.message[bookName].forEach(item => item())
}
}
const obj = new cs()
// 创建一些联系人
const user_1 = () => console.log('我是联系人1, 我来买书来了')
const user_2 = () => console.log('我是联系人2, 我来买书来了')
const user_3 = () => console.log('我是联系人3, 我来买书来了')
const user_4 = () => console.log('我是联系人4, 我来买书来了')
// 联系人开始预约书本
obj.add('劳动法', user_1)
obj.add('劳动法', user_2)
obj.add('劳动法', user_3)
obj.add('JS从入门到入土', user_4)
// 过了很长一段时间, 用户2 已经拿到赔偿了, 不需要看劳动法
obj.del('劳动法', user_2)
// 又过了一段时间, 劳动法 这本书到了, 开始通知联系人来买书
obj.tz('劳动法')
// 又过了一段时间, JS从入门到入土 这本书到了, 开始通知联系人来买书
obj.tz('JS从入门到入土')
数组扁平化
const data = [undefined, { name: 'QF001' }, 1, 2, 3, [4, 5, 6, [7, 8, 9]]]
// console.log(data)
// console.log([1, 2, 3, 4, 5, 6, 7, 8, 9])
/**
* 当前函数能够帮助我们完成数组的扁平化
*/
function flat(arr) {
// 1. 创建一个数组, 存储扁平化后的内容
const target = []
// 2. 核心代码: 完成扁平化
function setArr(origin) {
origin.forEach(item => {
if (Object.prototype.toString.call(item) !== '[object Array]') {
target.push(item)
} else {
// 当前分支只要执行, item 的值 一定是一个数组
setArr(item)
}
})
}
setArr(arr)
// 3. 将处理好的数据返回
return target
}
const res = flat(data)
console.log(res)
图片懒加载
- 在 图片 展示出来前, 我们不渲染图片
- 等到图片到达(快到达) 可视区域窗口的时候, 我们在渲染图片
const imgEl = document.querySelector('img')
window.onscroll = function () {
// console.log('开始判断')
if (imgEl.src !== '') return
// 屏幕的高度 + 页面卷去的高度 > 图片的顶部偏移量
const h = window.innerHeight
const pageH = document.documentElement.scrollTop
const top = imgEl.offsetTop
// - 200 是为了留出一点让网络请求图片的时间, 其实当前案例中 加不加 无所谓
if (h + pageH > top - 200) {
console.log('渲染图片')
imgEl.src = imgEl.dataset.src
}
}