回顾
ajax
ajax是一个异步的请求工具,主要提供对应的客户端和服务端之间的数据交互。它可以完成对应的局部刷新(同步加载页面整体会刷新,异步加载对应的页面不会进行刷新)核心对象
XMLHttpRequest)。
ajax的流程
- 创建xhr对象
- 打开连接
- 设置对应请求头
- 发送请求
- 监听事件接收数据(onreadystateChange)
get请求
get请求数据携带在对应的url中
post请求
post需要设置对应的请求头
xhr.setRequestHeader('Content-type','x-www-form-urlencoded')
post请求携带在请求体中
xhr.send(body)
JSONP
解决对应的跨域方案(主要利用script标签不受跨域影响 通过回调函数接收数据)实际上是一个get请求
步骤
- 准备一个回调函数(全局的)
- 准备一个script标签链入对应的地址 传入对应的参数及回调函数
- 加载完成 删除对应的script标签
设计模式
概述
设计模式是对应的一些处理方案形成的思想所构成的模式。主要是针对类和设计对象设计和构造的。它不区分语言,总共有23种设计模式(架构设计,源码设计)
设计模式的分类
- 创建型模式(关于对象的创建)
- 结构型模式(将多个小结构并入一个大结构)
- 行为型模式(对象的通信逻辑)
设计模式分类图
设计模式七大原则
- 单一责任原则
- 开闭原则
- 里氏置换原则
- 依赖倒转原则
- 接口隔离原则
- 迪米特法则
- 合成复用原则
主要讲解的模式
- 创建型模式(工厂模式、单例模式)
- 结构型模式(代理模式、装饰器模式、组合模式)
- 行为型模式(观察者模式)
工厂者模式
以工厂的形式来生产对象(不关注对象的细节)
function facotory(){
// 创建对象
let obj = {}
// 属性赋值
obj = Obj.name
// 返回对象
return obj
}
单例模式(饿汉、懒汉)
保证产生的对象只有一个(不会被污染)
利用闭包实现
// 利用闭包实现
function singleton(){
let single = null
// 判断是否为null 是否需要重新创建
return function(){
if(!single){
single = new Object()
}
return single
}
}
let singletonFn = singleton()
var obj = singletonFn()
var obj1 = singletonFn()
console.log(obj === obj1)
利用原型实现
// 原型实现
function singletonPrototype(){
// 判断原型上是否有这个对象
if(!Object.prototype.single){
Object.prototype.single = new Object()
}
return Object.prototype.single
}
var obj2 = singletonPrototype()
var obj3 = singletonPrototype()
console.log(obj2 === obj3)
利用静态属性实现
// 利用静态属性
function singleStatic(){
if(!Object.single){
Object.single = new Object()
}
return Object.single
}
var obj3 = singleStatic()
var obj4= singleStatic()
console.log(obj3 === obj4)
利用global对象实现
// 使用global globalThis 指向当前global对象 window
function singleGlobal(){
if(!globalThis.single){
globalThis.single = new Object()
}
return globalThis.single
}
var obj3 = singleGlobal()
var obj4= singleGlobal()
console.log(obj5 === obj6)
组合模式
将多个小结构合成一个大结构(将共有函数放在一起调用)
示例
// 将多个小结构合成一个大结构
function One(){
this.init = function(){
console.log('1')
}
}
function Two(){
this.init = function(){
console.log('2')
}
}
function Three(){
this.init = function(){
console.log('3')
}
}
// 一个个调用 123
new One().init()
new Two().init()
new Three().init()
将init方法 一起执行 利用组合模式来执行多个同名方法
// 将init方法 一起执行 利用组合模式来执行多个同名方法
function Combination(){
this.objs = []
// 传入对应的对象
this.add = function(...objs){
// 接收对应的对象数组
this.objs = this.objs.concat([...objs])
}
// 执行对应的里面的init方法 以参数传递函数名的形式来执行
this.exec = function(fnName){
// 遍历对应的对象数组
this.objs.forEach((obj)=>{
// 调用对应的方法
obj[fnName].call(this)
})
}
}
let combination = new Combination()
combination.add(new One(),new Three())
combination.exec('init')
组合模式的应用 Vue里面use和install
class Vue{
// 解析对应的对象 执行对应的install
static use(...objs){
objs = objs.map(v=>{
// 如果没有install方法
if(!v.install){
if(typeof v != 'function'){
throw new Error('传入内容出错')
}
// 将本身当做install
let fn = v
v= {
install(){
fn()
}
}
}
return v
})
Vue.exec(objs)
}
// 传入对象进行执行
static exec(arr){
arr.forEach(obj => {
obj['install'].call(this.Vue)
});
}
}
Vue.use({
install(){
console.log('吃饭吃饭')
}
},{
install(){
console.log('睡觉睡觉')
}
})
Vue.use({
install(vue){
console.log(Vue)
console.log('哈哈')
}
})
装饰器模式
用一个新的类将对应的原本的对象进行包装再进行加强(在不改变原有对象的基础上增强对象)
function Person() {
this.run = function () {
console.log('跑')
}
}
//传入要增强的对象 返回一个新的对象
function Stronger(person) {
this.person = person
this.run = function () {
this.person.run()
console.log('我会飞')
}
}
//基础对象
let person = new Person()
person.run() //跑
//增强的对象
let stronger = new Stronger(person)
stronger.run() //跑 我会飞
Ts内置有对应的装饰器 Decorator Ts中使用注解来进行对应的装饰器添加 @decorator
代理模式
概述代理模式是在原有对象的基础上增强对应的对象(利用代理对象来增强)代理对象通常访问的是实际的对象
注意事项
- 代理对象对原本的对象进行了功能增强
- 代理对象影响的是实际的对象
ES7新增对应的Proxy的类 来帮助我们进行代理
Proxy(vue3的底层实现)
实例化(传入对应的被代理对象 处理对象 产生一个代理对象)
var proxy = new Proxy(target,handler)
示例
var obj = {
name : 'joe',
age : 22
}
// 代理对象 传入被代理对象 及 处理对象
// 在proxy里面的get set 不要使用proxy处理对象
var proxy = new Proxy(obj,{
// 获取相关的属性 被代理对象 属性名 代理对象
get(targeObj,attrName,proxyObj){
let result = targeObj[attrName]
if(result == 'age'){
result += '岁'
}else if(result == 'name'){
result = '我的名字叫'+result
}
},
// 获取相关的属性 被代理对象 属性名 属性值 代理对象
set(targeObj,attrName,attrValue,proxyObj){
if(typeof attrValue != 'number' && attrName == 'age'){
throw new Error('你传入的不是一个数字')
}
return targeObj[attrName] = attrValue
}
})
// 使用代理对象
console.log(proxy.name) //访问get方法
proxy.name = 'jack' //访问set方法
console.log(proxy.name)
// proxy.age = 'abc'
console.log(obj.name)
proxy的handler相关属性和方法
观察者模式
概述
观察者模式是前端最常用的模式,它相当于对应的监听和处理执行的机制。观察者模式别obServer又被称为发布者-订阅者模式。
常见的发布者订阅者模式
addEventListener (事件监听器)
var box = document.querySelector('.box')
// element.addEventListener(事件名,handler)
box.addEventListener('click',function(){
// 处理
console.log('好看的一个盒子')
})
- 你 发布者 (box添加点击事件)
- js事件处理线程 订阅者 (添加事件监听 保持监听)
- 处理 处理函数 订阅者 (订阅者进行处理)
实现发布者订阅者模式
模仿eventListener来实现
事件监听 on
// 监听事件传入一个事件名和对应的处理函数
on(eventName, handler) {
// 判断是否储存了对应的事件
if (eventName in this.events) {
// 如果存储了就给他加到对应的处理函数数组内
this.events[eventName].add(handler)
} else {
// 如果没有的话需要先开辟一个数组 将处理的函数装入
this.events[eventName] = new Set([handler])
}
}
事件执行 emit
// 执行对应的处理函数 传入对应的事件执行对应的处理函数 传入对应的参数传递给处理函数
emit(eventName, ...args) {
// 如果不存在对应的事件 就退出
if (!this.events[eventName]) {
return;
}
// 存在就遍历对应的集合 调用对应的处理函数
this.events[eventName].forEach(handler => {
handler.apply(this, args)
});
}
事件取消 off
// 移除事件监听器
off(eventName, handler) {
// 查询是否具备对应的事件
if (!this.events[eventName]) {
return;
}
this.events[eventName].delete(handler)
}
完整版实现
class Observer {
constructor() {
//存储事件的容器和处理函数的容器{click:[handler],mousedown:[handler]}
this.events = {}
}
// 监听事件传入一个事件名和对应的处理函数
on(eventName, handler) {
// 判断是否储存了对应的事件
if (eventName in this.events) {
// 如果存储了就给他加到对应的处理函数数组内
this.events[eventName].add(handler)
} else {
// 如果没有的话需要先开辟一个数组 将处理的函数装入
this.events[eventName] = new Set([handler])
}
}
// 执行对应的处理函数 传入对应的事件执行对应的处理函数 传入对应的参数传递给处理函数
emit(eventName, ...args) {
// 如果不存在对应的事件 就退出
if (!this.events[eventName]) {
return;
}
// 存在就遍历对应的集合 调用对应的处理函数
this.events[eventName].forEach(handler => {
handler.apply(this, args)
});
}
// 移除事件监听器
off(eventName, handler) {
// 查询是否具备对应的事件
if (!this.events[eventName]) {
return;
}
this.events[eventName].delete(handler)
}
}