typora-root-url: images
typora-copy-images-to: images
单例模式
什么是单例模式
单例模式也称作为单子模式,单体模式。单例模式的定义是产生一个类的唯一实例,是软件设计中较为简单但是很常用的一种设计模式。
单例模式的核心是确保只有一个类一个实例,并提供全局访问.
单例的使用
核心思想
无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象
多次实例化,返回一个对象
function fn(){
console.log(1111);
if(!fn.obj){
fn.obj={
name:'cheng'
}
}
return fn.obj;
}
var obj1 = new fn();
var obj2 = new fn();
console.log(obj1==obj2);
分析:
这是一个最经典的惰性单例,如果实例不存在,通过一个方法创建一个实例,如果已经存在,则返回实例的引用。这里就说明了它和静态对象不同,可以被延迟生成,也就是说在我们需要的时候才创建对象实例,而非在页面加载时就创建。
ES6中的实现
class A{
obj = '';
say(){
console.log('哈哈');
}
static getObj(){
if(!this.obj){
this.obj = new A;
}
return this.obj;
}
}
let a1 = A.getObj();
let a2 = A.getObj();
console.log(a2);
console.log(a1===a2);
单例模式实现弹出框(了解)
不管点击多少次,只会实例化一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
/*
自定义弹出层
+ 从 html 到 css 到 js 效果全部由 Dialog 类实现
*/
// 需要弹出层的时候
// success 成功 绿色
// warning 警告 橘黄色
// danger 危险 红色
// info 信息 蓝色
// default 默认 白色
const Dialog = (function () {
// 专门准备一个设置 css 样式的方法
// ele 表示给哪一个元素设置
// styles 表示设置哪些样式 { left: '100px', right: '200px' }
function setStyle(ele, styles) {
for (let k in styles) {
ele.style[k] = styles[k]
}
}
// 照常书写构造函数
class Dialog {
constructor () {
// 创建一个 div
this.ele = document.createElement('div')
// 准备一个备选的数组
this.status = [
{ color: '#fff', text: '', type: 'default' },
{ color: 'orange', text: '警告', type: 'warning' },
{ color: 'green', text: '成功', type: 'success' },
{ color: 'red', text: '错误', type: 'danger' },
{ color: 'skyblue', text: '信息', type: 'info' }
]
this.init()
}
// 准备 init 函数
init () {
// 设置 div 内部的结构
this.setDivInnerHtml()
// 设置 div 内部的样式
this.setDivInnerStyle()
// 设置 div 内的事件
this.setEvent()
// 把 div 插入到页面
document.body.appendChild(this.ele)
}
// 准备 change 函数
change (type, msg) {
// 调整 top 和 bottom 的颜色
// 1. 确定颜色
const status = this.status.find(item => item.type === type) || { color: '#fff', text: '', type: 'default' }
// 2. 调整颜色
this.setColors(status)
// 3. 修改文本
this.setText(msg)
// 4. 让 this.ele 显示出来
this.ele.style.display = 'flex'
}
// 需要一个方法, 确定 div 内的 html 结构
setDivInnerHtml () {
this.ele.innerHTML = `
<div class="top">
错误
</div>
<div class="center">
注册失败, 该用户名已经被占用
</div>
<div class="bottom">
<button>关闭</button>
</div>
`
}
// 需要一个方法, 设置 div 及内部所有标签的样式
setDivInnerStyle () {
// this.ele 设置样式, 设置好几个
// this.ele 下面的 .top 需要设置 好几个
// this.ele 下面的 .bottom 需要设置 好几个
setStyle(this.ele, {
width: '500px',
height: '300px',
border: '3px solid #333',
'background-color': '#fff',
position: 'fixed',
top: '0',
left: '0',
right: '0',
bottom: '0',
margin: 'auto',
display: 'none',
'flex-direction': 'column'
})
const topBox = this.ele.querySelector('.top')
const centerBox = this.ele.querySelector('.center')
const bottomBox = this.ele.querySelector('.bottom')
const btn = this.ele.querySelector('button')
setStyle(topBox, {
height: '35px',
display: 'flex',
'align-items': 'center',
'box-sizing': 'border-box',
padding: '0 20px',
'background-color': 'red',
color: '#fff'
})
setStyle(bottomBox, {
height: '35px',
display: 'flex',
'align-items': 'center',
'box-sizing': 'border-box',
padding: '0 20px',
'background-color': 'red',
color: '#fff',
'justify-content': 'flex-end'
})
setStyle(centerBox, {
flex: '1',
display: 'flex',
'justify-content': 'center',
'align-items': 'center',
'font-size': '24px'
})
setStyle(btn, {
cursor: 'pointer'
})
}
// 需要一个方法, 能让 div 隐藏起来
setEvent () {
const btn = this.ele.querySelector('button')
btn.addEventListener('click', () => {
this.ele.style.display = 'none'
})
}
// 需要一个方法, 调整 .top 和 .bottom 的颜色
setColors ({ color, text }) {
const topBox = this.ele.querySelector('.top')
topBox.style['background-color'] = color
topBox.innerText = text
const bottomBox = this.ele.querySelector('.bottom')
bottomBox.style['background-color'] = color
}
// 需要一个方法, 调整 .center 内的文本内容
setText (msg) {
const centerBox = this.ele.querySelector('.center')
centerBox.innerText = msg
}
}
// 单例模式核心代码
let instance = null
return function (type, msg) {
if (!instance) instance = new Dialog()
instance.change(type, msg)
return instance
}
})()
new Dialog('warning', '删除后不能恢复')
</script>
</body>
</html>
Web Storage
cookie
认识 cookie
- cookie中的数据 可以被同一个网站的页面所共享
- 不同浏览器的cookie 不能共享
- cookie的数据存储在浏览器中,每次请求服务器,在请求报文中携带cookie的数据,发送给服务器
- 服务器端无法直接操作cookie,是通过在服务器端设置响应头的的方式,通知浏览器对cookie进行设置,
- cookie中的数据有效期,不设置是会话级别的, 浏览器关闭,会话结束,数据销毁,可以人为设置cookie的有效期
- cookie存储容量小,约4kb
操作cookie
一定通过服务器的方式就行访问
基本使用
语法格式
设置cookie:
document.cookie="username=John;expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
存储的值 有效时间 适用范围
注意:此处的有效期是时间字符串.
读取cookie
document.cookie
删除cookie
直接设置时间过期
例1:通过cookie存储name,age,addr数据
// 1. 设置, 要求 键值对, 通过 = 分隔
document.cookie = "name=fengfeng";
document.cookie = "age=18";
document.cookie = "desc=shuai";
//2. 获取, document.cookie 一次性将所有的 cookie 都获取, 以字符串的形式返回
//通过 "; " 分隔, name=pengpeng; age=18; desc=shuai
console.log( document.cookie );
// 获取cookie中的值
document.cookie;
问题:一次性存储多个cookie后,没办法获取指定的
例2:设置一个cookie的hobby=maomi一分钟后过期
let d = new Date(); // 获取当前时间对象
let time = d.getTime(); // 获取时间戳
let time1 = d.setTime(时间戳); // 设置需要格式化的事件戳
let expires = d.toGMTString(); // cookie 的有效期,计时不是按照中国时区,所以需要转化
let d = new Date();
let time = d.getTime(); // 单位是毫秒
//console.log(time)
//向后设置一分钟
d.setTime(time+1*60*1000);
let exp = d.toGMTString();
// console.log(exp)
// 设置cookie,为一分钟过期
// 设置cookie过期的是expires
// document.cookie='qi=压岁钱;expires='+exp;
cookie的读取封装
class Cookie {
// 设置cookie
static setCookie (name, val, exp = 0) {
// 判断是否设置时间
if (exp) {
let d = new Date();
let ms = d.getTime();
d.setTime(exp * 60 * 1000 + ms);
// 获取且转化为时间字符串
exp = d.toGMTString();
}
// cookie的设置
document.cookie = `${name}=${val};expires=${exp}`;
}
// cookie的获取
static getCookie(key) {
// 1 判断是否传值
if (!key) return;
// 2 取出cookie
// console.log(document.cookie);
let vals = document.cookie;
// 2-1 为空则不继续执行
if (!vals) return null;
// 2-2 不为空,则分割
vals = vals.split(';');
console.log(vals);
// 2-3 遍历寻找目标key
let data = '';
// v 是数组的元素
vals.forEach((v, i) => {
console.log(v.trim());
// 2-4 找到下标不为-1且为0的,就是要取的key
// console.log(v.trim().indexOf(key));
if (v.trim().indexOf(key) == 0) {
// console.log((v.split('='))[1]);
// forEach内部函数的返回值,外部接收不到
// return (v.split('='))[1];
data = (v.split('='))[1];
}
});
return data;
}
}
cookie的加密
md5加密和base64的加解密
js中session操作
// 保存数据到sessionStorage
sessionStorage.setItem('key', 'value');
// 从sessionStorage获取数据
var data = sessionStorage.getItem('key');
// 从sessionStorage删除保存的数据
sessionStorage.removeItem('key');
// 从sessionStorage删除所有保存的数据
sessionStorage.clear();
localStorage 是js中最常见的存储方式.
cookie和session主要在服务器端使用,保存一次会话信息.PHP.java,NodeJs
面试题
本地存储(记住)
- 指: 说一下 cookie localStorage sessionStroage 的区别
1. 存储大小
cookie 4KB 左右
=> localStorage/sessionStroage 20MB 左右
2 自动携带
cookie 会跟随请求自动携带在请求头内
=> localStorage/sessionStroage 不会自动携带需要手动设置
3 时效性
localStorage 永久
=> sessionStroage 会话
=> cookie 默认会话级别, 可以自定义设置过期时间
4. 存储位置
cookie 必须依赖域名存储
=> localStorage/sessionStroage 可以在本地状态下使用
5 前后端操作
cookie 前后端都可以操作
=> localStorage/sessionStroage 只能前端操作, 后端不行
6 session(补充)
=> 一个服务器端的存储空间
=> 用来支持登陆状态保持的
=> 当 session 空间开启以后, 会生成一个 sessionID 的内容自动放在 cookie 内
面试题:数组塌陷
<script>
var arr = [1, 2, 3, 4, 5, 6];
// 删除数组中的元素,删除不干净
// for (var i = 0; i < arr.length; i++) {
// arr.splice(i, 1)
// }
// console.log(arr); // 删除不干净,因为i在变化
// 方法1: 设置删除起始位置是0
// var length = arr.length;
// for (var i = 0; i < length; i++) {
// arr.splice(0, 1)
// }
// 方法2:从尾巴,倒着删除
// for (var i = arr.length - 1; i >= 0; i--) {
// arr.splice(i, 1)
// }
// 方法3:让i永远为0,永远删除第一个元素
for (var i = 0; i < arr.length; i++) {
arr.splice(i, 1);
//console.log('a' + i);
i--;
console.log(i);
}
console.log(arr);
</script>