1、常用概念
typeof: 获取类型let age = 10; console.log(typeof age); //打印结果 number
1.1、数据类型
- Null : 值被定义了,但定义为
空值,没有值的变量 - Undefined : 表示缺少值,此处应该有一个值,
未定义的变量
1.2、字符串
1.2.1、字符串方法
- 常规方法
- .length : 获取长度
- .toLowerCase() : 转小写(不改变原有字符串)
- .toUpperCase() : 转大写
let fullName = 'L' + ' ' + 'z'; let result = fullName.toLowerCase(); console.log(result, fullName); - .includes() : 是否包含某个字符,返回boolean值
- 查询字符位置
- .indexOf() : 获取字符第一次出现的位置
- .lastIndexOf : 获取字符最后出现的位置
let email = '1556666666@qq.coM'; let index = email.indexOf('6'); let lastIndex = email.indexOf('6'); console.log(index,lastIndex);
- 截取字符串
.slice(): 截取字符串(起始位置,结束位置)let result = email.slice(0, 5); console.log(result);- .substr() : 截取字符串(起始位置,向后多少位)
let result = email.substr(2, 5); console.log(result);
- 替换字符串
.replace(): 替换字符,仅替换第一次出现的let result = email.replace('M', 'm'); result = result.replace('q', 'Q'); console.log(result);
1.2.2、模板字符串
-
比 "+号" 更灵活的字符串组合方式,使用反引号 ` 定义模板字符串,
${变量名}插入变量名const myName = 'LZ'; const myAge = '5'; const mySex = '男生'; let result = `我的名字叫${myName},今年${myAge}岁了,是个${mySex}`; console.log(result); -
创建HTML模板(后续可用于插入到html文件中)
let html = ` <h2>${myName}</h2> <p>${myAge}</p> <span>我的性别是${mySex}</span> `;
1.3、数字
1.3.1、运算符
**: 次方//6的3次方 let result = 6 ** 3; console.log(result);
1.3.2、NaN
- Not a Number,当计算数字时出现了非数字量时出现的异常
//数字与字符串做运算会出现 NaN console.log(10 / 'lz');
1.4、数组
.join(): 将数组中的内容添加指定的分隔符转换成字符串let users = ['lz',25,'男','lz']; let result = users.join(','); console.log(result);- indexOf() : 查询内容在数组中第一次出现的位置(没有的话返回-1)
let index = users.indexOf('lz'); console.log(index); - .includes() : 是否包含某个元素,返回boolean值
.concat(): 连接数组let result = users.concat(['读书' , 10]); console.log(result);- 增删数组
- .push() : 在尾部追加元素,返回内容为
新数组长度,改变原有数组let result = users.push('跑步'); console.log(result); //打印结果 5 - .pop() : 删除尾部元素,返回内容为
被删除元素,改变原有数组let result = users.pop(); console.log(result); //打印结果 lz
- .push() : 在尾部追加元素,返回内容为
1.5、函数
- 函数声明
function func1(){ console.log('func1'); }; func1(); - 函数表达式
//设置形参,并且为time设置默认值 const func2 = function(name , time = 10){ console.log(`My Name is ${name},this time is ${time} o'clock`); }; func2('LZ'); //打印结果 My Name is LZ,this time is 10 o'clock - 函数声明与函数表达式的区别
- 函数声明会被编译器提升到顶部,即写在最下边也能调用成功,但函数表达式如果写在调用方法之后会报错
1.5.1、回调函数
- 在一个函数完成执行后执行的函数(
函数做参数)const myFunc = (callback) => { let value = 10; callback(value); };
1.5.2、.foreach()
- 遍历内容
- .foreach() 中放函数方法,可直接写也可提取出去;可有3个参数:
元素、角标、整体集合let personArr = ['张三','李四','王五',['木头六','雀斑七']]; personArr.forEach((person, index, numberArr) => { console.log(`${person} - ${index} - ${numberArr}`); }); //打印结果 张三 - 0 - 张三,李四,王五,木头六,雀斑七 李四 - 1 - 张三,李四,王五,木头六,雀斑七 王五 - 2 - 张三,李四,王五,木头六,雀斑七 木头六,雀斑七 - 3 - 张三,李四,王五,木头六,雀斑七
1.6、对象字面量
- 创建对象,可添加方法,但要注意
this关键字时不能用在箭头函数中,简写可省略冒号与functionlet user = { name : 'LZ', hobbies : ['Sing','Jump','Rap'], eat : function (food) { console.log(`吃${food}`); }, play : (sport) => { console.log(`玩${sport}`); }, //简写方法,省略 冒号与function enjoy(name) { this.hobbies.forEach((hobby) => { console.log(`${name}有${hobby}兴趣`); }); }, //错误写法,箭头函数中不能用this mistakeEnjoy : (name) => { this.hobbies.forEach((hobby) => { console.log(hobby); }); } }; user.eat('小笼包'); user.play('篮球'); user.enjoy('LZ'); user.mistakeEnjoy('LZ'); //打印结果 吃小笼包 玩篮球 LZ有Sing兴趣 LZ有Jump兴趣 LZ有Rap兴趣 Uncaught TypeError TypeError: Cannot read properties of undefined (reading 'forEach') at mistakeEnjoy (/Volumes/Disk_D/js test/sandbox.js:74:22) at <anonymous> (/Volumes/Disk_D/js test/sandbox.js:83:6)
1.7、Math
- Math.round() : 四舍五入
- Math.floor() : 向下取整
- Math.ceil() : 向上取整
- Math.random() : 0 ~ 1间随机数
2、DOM(Document Object Model)
2.1、查询选择器
2.1.1、.querySelector()
- 查询输入的条件下,第一次出现的内容
//CSS <body> <div> <h1>Hello World</h1> <p>p标签</p> <p class="pp">我的p标签</p> </div> <div class="pp">第二个div</div> <script src="sandbox.js"></script> </body>- 按标签查询 : 直接填入标签名
//打印第一次出现的 p标签 内容 const paragraph = document.querySelector('p'); console.log(paragraph); //打印内容 <p>p标签</p> - 按类名查询 :
.号开始//查询类名为 pp 的 const paragraph = document.querySelector('.pp'); console.log(paragraph); //打印内容 <p class="pp">我的p标签</p> - 重复类名查询 :
标签名.类名精确查询//查询类名为 pp 的 div 标签 const paragraph = document.querySelector('div.pp'); console.log(paragraph); //打印内容 <div class="pp">第二个div</div>
- 按标签查询 : 直接填入标签名
- .querySelectorAll() : 查询输入的条件下,所有出现的内容,返回
节点列表,类似于数组,可以使用foreach遍历
2.1.2、其他查询选择器
- .getElementById()
- 通过Id唯一获取,返回节点
- .getElementsByClassName()
- 通过类名获取
HTMLCollection集合
- 通过类名获取
- .getElementsByTagName()
//获取 p标签 const paragraph = document.getElementsByTagName('p'); console.log(paragraph); //打印结果 HTMLCollection [p.pp]- 通过标签获取 HTMLCollection 集合
节点列表与HTMLCollection区别
- DOM树中,节点列表 可以包含 元素 和 文本节点,而 HTMLCollection 只包含 HTML元素集合,不包含 文本节点
- 节点列表 类似数组,
可以使用foreach遍历;HTMLCollection 是元素集合,不能使用foreach方法遍历 - HTMLCollection可以通过
Array.from()转化成数组,从而使用 .foreach()//不改变原有结构 Array.from(document.getElementsByTagName('p'));
2.2、内容修改
.innerText: 文本操作- 与
.textContent的异同:- 都是获取文本的操作
- .innerText 获取不到内部包含隐藏属性(style ="display:none")的标签的标签,但 .textContent 可以
//.innerText获取不到这种 <p>标签<span style="display:none">隐藏标签</span></p> - 平时可以多用 .textContent
- 与
.innerHTML: 元素操作//替换 p标签 const contents = document.getElementsByClassName('pp'); contents[0].innerHTML = '<p>替换的p标签</p>';
2.2.1、.Attribute()
- 获取
元素属性值,用于对属性进行操作,可用性不高,因为会将属性值整个覆盖,导致原有设置失效 - .getAttribute() : 获取属性值
- .setAttribute() : 设置属性值
示例
//CSS创建个a标签
<body>
<a href="https://www.bilibili.com">哔哩哔哩链接</a>
<script src="sandbox.js"></script>
</body>
const contents = document.getElementsByTagName('a');
console.log(contents[0].getAttribute('href'));
//对多种属性进行替换
contents[0].innerText = '百度链接';
contents[0].setAttribute('href','https://www.baidu.com');
contents[0].setAttribute('class','myClass');
contents[0].setAttribute('style','color:green');
2.2.2、.style.xx
- 通过
.style.获取多种属性进行设置,相比 Attribute 好处是不会整体覆盖,增量修改 - 也不会大量使用,因为一个个设置效率太低,所以
样式的设置一般设置类样式,然后通过将元素加入不同的类中实现
const title = document.querySelector('p');
title.style.color = 'red';
title.style.margin = '100px';
2.2.3、增加、删除类
.classList: 类列表- .add() : 添加类
- .remove() : 删除类
.toggle(): 切换,已有则移除,没有则添加
//增加myClass类,在CSS中寻找并实现这个类的样式
const title = document.querySelector('a');
title.classList.add('myClass');
title.classList.remove('myClass');
title.classList.toggle('myClass');
2.3、相关元素
- 父元素、子元素、兄弟元素
const title = document.querySelector('a');
//父元素
console.log(title.parentElement);
//子元素
console.log(title.children);
//下一个兄弟元素
console.log(title.nextElementSibling);
//上一个兄弟元素
console.log(title.previousElementSibling);
3、事件
addEventListener(): 添加事件监听- 执行函数中可以提供事件
event,通过.target可以定位点击的目标
const title = document.querySelector('a');
title.addEventListener('click', (e) => {
e.target.style.textDecoration = 'line-through';
});
3.1、添加删除元素
.append(): 尾部追加、.prepend(): 头部追加
const title = document.querySelector('a');
title.addEventListener('click', (e) => {
//innerHTML方式增加
title.innerHTML += '<li>新元素</li>';
//创建Element追加
const li = document.createElement('li');
li.textContent = '另一个新元素';
title.prepend(li);
});
3.2、代理和冒泡
-
事件冒泡 : 事件会向上传递,点击子元素时,父元素也会响应事件
const title = document.querySelector('a'); title.addEventListener('click', (e) => { //阻止事件响应 e.stopPropagation(); }); -
事件代理 : 可以通过将事件添加到父元素,具体哪个子元素响应的定位,用
e.target.tagName判断,这样可以对所有兄弟元素有相同操作,不会出现新添加的兄弟元素响应不了事件的情况//CSS样式 <body> <a href='https://www.bilibili.com'>哔哩哔哩链接</a> <li>原有li</li> <button>添加li元素</button> <script src="sandbox.js"></script> </body>const title = document.querySelector('a'); const btn = document.querySelector('button'); btn.addEventListener('click',(e)=>{ const li = document.createElement('li'); li.textContent = '新元素'; title.prepend(li); }); const mybody = document.querySelector('body'); //监听添加到父元素,但响应在子元素,通过 e.target.tagName 区分具体是哪个子元素 mybody.addEventListener('click', (e)=>{ if (e.target.tagName === 'LI') { e.target.remove(); } });
3.3、各种事件
- click : 点击事件
- copy : 被copy内容时
- mousemove : 鼠标在元素上移动时
element.addEventListener('click', (e)=>{});
element.addEventListener('copy', (e)=>{});
element.addEventListener('mousemove', (e)=>{});
4、表单
4.1、表单提交事件
<body>
<form action="" class="signup-form">
<input type="text" name="userName" placeholder="姓名">
<input type="submit" value="提交">
</form>
<script src="sandbox.js"></script>
</body>
const form = document.querySelector('.signup-form');
form.addEventListener('submit',(e)=> {
//禁止点击提交按钮后的刷新动画
e.preventDefault();
//CSS中设置name和id为userName 这里点语法都能调用成功
console.log(form.userName.value);
});
4.2、正则表达式验证提交内容
-
正则表达式以
//包裹中间内容表示[]: 表示允许的 符号范围{}: 表示 限定位数^: 表示以后边的 限定内容开头$: 表示以后边的 限定内容结尾.test(): 对内容进行正则校验,返回boolean值
const username = '1234myuser'; //以数字0-9开头,最少2位,最多4位 //以大写或小写的字母结尾,最少6位 const pattern = /^[0-9]{2,4}[a-zA-Z]{6,}$/; //.test()方法对内容进行正则验证 let result = pattern.test(username); console.log(result);注 : 如果不加 ^ 与 $ ,则只是检查字符串中是否包含符合条件的内容
-
规则与验证可以查看 正则表达式在线网站
4.3、监听键盘输入
- 对 id或name 为userName的 input标签 进行监听,监听关键字 'keydown'为按下 ,'keyup'为按钮弹起,'keypress'为整个按完过程
const form = document.querySelector('.signup-form');
//监听键盘输入
form.userName.addEventListener('keydown',(e)=> {
const pattern = /^[0-9]{2,4}[a-zA-Z]{6,}$/;
if (pattern.test(e.target.value)) {
//正则匹配成功设置class为success,是预设的匹配成功时的CSS样式
form.userName.setAttribute('class','success');
} else {
form.userName.setAttribute('class','error');
}
});
5、数组方法
5.1、.filter()
- 过滤,不破坏原有数组
const scores = [12,24,6,50,31,5];
const filterScores = scores.filter((score) => {
//返回return值为true的内容
return score > 10;
});
console.log(filterScores);
//打印结果
[12, 24, 50, 31]
5.2、.find()
- 只返回第一个return为true的内容
const scores = [12,24,6,50,31,5];
const findScore = scores.find((score) => {
//返回return值为true的内容
return score > 10;
});
//打印结果
12
5.3、.map()
- 映射,可对元素进行处理
const fruits = [
{ name: 'apple', salePrice: 10 },
{ name: 'orange', salePrice: 6 },
{ name: 'banana', salePrice: 4 },
{ name: 'grape', salePrice: 15 },
];
const saleFruits = fruits.map((product) => {
//筛选价格在10元以上的半价
if (product.salePrice >= 10) {
//这么写会改变原有数组内容
//return product.salePrice = product.salePrice / 2;
return {name : product.name , salePrice : product.salePrice / 2};
} else {
return product;
}
});
console.log(saleFruits);
5.4、.reduce()
- 常用3个参数,处理接收参数、回调函数、接收参数默认值
//myParam为自定义的接收函数处理的参数
const reduceFruitsPrice = fruits.reduce((myParam , fruit) => {
if (fruit.salePrice > 5) {
myParam = (Number(myParam) + fruit.salePrice).toString();
}
return myParam;
// '0'是用户为myParam添加的默认值
}, '0');
5.5、.sort()
- 排序,改变原有数组,如果不加
比值函数,则按位比较ASCII码(数字会出现例如1、20、3、423这种情况)
//普通排序
const scores = [12,24,6,50,31,5];
console.log(scores.sort());
//比值函数
const fruits = [
{ name: 'apple', salePrice: 10 },
{ name: 'orange', salePrice: 6 },
{ name: 'banana', salePrice: 4 },
{ name: 'grape', salePrice: 15 },
];
//注意有{}要加return,拿掉{}可以不加return
fruits.sort((a,b) => {return a.salePrice - b.salePrice});
console.log(fruits);
6、日期与时间
6.1、日期与时间获取
//创建日期对象
const nowDate = new Date();
console.log(nowDate, typeof nowDate);
//日期字符串
console.log('toDateString -- 日期:',nowDate.toDateString());
console.log('toTimeString -- 时分秒:',nowDate.toTimeString());
console.log('toLocaleString -- 本地时间:',nowDate.toLocaleString());
console.log('toLocaleDateString -- 本地日期:',nowDate.toLocaleDateString());
console.log('toLocaleDateString -- 本地时分秒:',nowDate.toLocaleTimeString());
//通过日期对象的方法获取时间的值
console.log('getTime -- since1970:',nowDate.getTime());
console.log('getFullYear -- 年份:',nowDate.getFullYear());
console.log('getMonth -- 月份:',nowDate.getMonth()); //注意获取月份是从0开始,所以使用时要+1
console.log('getDate -- 日期:',nowDate.getDate());
console.log('getDay -- 星期:',nowDate.getDay()); //注意星期天是0
console.log('getHours -- 时:',nowDate.getHours());
console.log('getMinutes -- 分:',nowDate.getMinutes());
console.log('getSeconds -- 秒:',nowDate.getSeconds());
- 通过时间戳获取时间
const timestamps = 1628602116106; const time = new Date(timestamps); console.log(time);
6.2、时间戳日期比较
//自定义一个时间的时间戳
const someDay = new Date('February 1 2022 22:15:30');
const nowDate = new Date();
//计算时间相差的毫秒数
const diff = nowDate.getTime() - someDay.getTime();
const mins = Math.round(diff / 1000 / 60);
const hours = Math.round(mins / 60);
const days = Math.round(hours / 24);
console.log('相差 -- ',mins,'分钟',hours,'小时',days,'天');
//打印结果
相差 -- 111637 分钟 1861 小时 78 天
6.3、setInterval()
- 定时器,参数为 方法函数 ,毫秒为单位
const title = document.querySelector('h1');
//定义一个方法函数
const tick = () => {
const now = new Date();
const h = now.getHours();
const m = now.getMinutes();
const s = now.getSeconds();
const html = `
<span>${h}</span>
<span>${m}</span>
<span>${s}</span>
`;
title.innerHTML = html;
}
//定时器,参数为方法函数,毫秒为单位
setInterval(tick, 1000);
6.4、setTimeOut()
- 延迟执行,参数为 方法函数 ,毫秒为单位
setTimeOut(() => {
console.log('延迟2秒执行');
}, 2000);
dayjs
- 常用时间插件,Day.js中文网
7、异步
7.1、XMLHTTPRequest网络请求
XMLHttpRequest(): 创建网络请求
简单示例
//对网络请求进行封装,请求完毕通过 callback回调函数 返回内容
const requestData = (urlPath, callback) => {
//网络请求对象
const request = new XMLHttpRequest();
//监听请求状态
request.addEventListener('readystatechange' ,() => {
//HTTP 响应已经完全接收,并且响应码正常
if(request.readyState === 4 && request.status === 200) {
if(request.status === 200) {
//将返回的字符串转换为JSON
const jsonData = JSON.parse(request.responseText);
callback(undefined, jsonData);
} else {
callback('无法获取数据', undefined);
}
}
});
//初始化 HTTP 请求参数,例如 URL 和 HTTP 方法,但是并不发送请求
request.open('GET', urlPath);
//发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体
request.send();
}
//调用网络请求,传入接口
requestData('http://jsonplaceholder.typicode.com/todos', (err, data) => {
console.log(`请求状态:${err}`,'数据为:',data ,typeof data);
});
7.2、Promise
- 为了实现在 等待其他请求完成后再执行 操作的场景
- promise对象 中 参数为一个回调函数,这个回调函数有两个参数:
resolve与reject分别 也都是回调函数,两者并不同时执行,成功时执行resolve,失败时执行reject .then(): 等待前面方法执行完毕后再执行,获取promise的 resolve 与 reject 方法,可以获取promise中rerurn的内容.catch(): 等待执行监听reject方法
改进示例
//去掉callback参数
const requestData = (urlPath) => {
//返回 promise对象
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.addEventListener('readystatechange' ,() => {
if(request.readyState === 4 && request.status === 200) {
if(request.status === 200) {
const jsonData = JSON.parse(request.responseText);
//成功,执行resolve方法
resolve(jsonData);
} else {
//失败,执行reject方法
reject('无法获取数据');
}
}
});
request.open('GET', urlPath);
request.send();
})
}
//等待请求完毕后 .then()获取 promise 的两个回调函数(此处只写一个), .catch()获取 reject回调函数
requestData('http://jsonplaceholder.typicode.com/users')
.then((data) => {
console.log('请求数据为:',data ,typeof data);
return requestData('http://jsonplaceholder.typicode.com/albums');
}).then((data) => {
console.log('请求数据为:',data ,typeof data);
}).catch((err) => {
console.log('请求状态为:',err ,typeof err);
});
7.3、fetch()网络请求
- 无论成功与否,都会返回 promise 对象,与Promise对象resolve与reject方法二选一不同,fetch() 即使走 .catch() 方法,还是会走 resolve 方法
7.3.1、Get请求
fetch('http://jsonplaceholder.typicode.com/users')
.then((response) => {
console.log('resolve:', response);
//直接获取json数据
return response.json();
}).then((data) => {
console.log(data);
}).catch((err) => {
console.log('reject:', err);
});
7.3.2、Post请求
- 表单提交
fetch('http://jsonplaceholder.typicode.com/users', { method: 'post', body: 'userName=13342262638&pwd=123456', headers: { 'Content-Type' : 'application/x-www-form-urlencoded' }, }).then((response) => { console.log('resolve:', response); return response.text(); }).then((data) => { console.log(data); }).catch((err) => { console.log('reject:', err); }); - JSON提交
fetch('http://jsonplaceholder.typicode.com/users', { method: 'post', body: JSON.stringify({ userName : "LZ", pwd : "123456" }), headers: { 'Content-Type' : 'application/json', 'token' : 'myToken' }, }).then((response) => { console.log('resolve:', response); return response.text(); }).then((data) => { console.log(data); }).catch((err) => { console.log('reject:', err); });
其它参数详细配置
-
method: 请求使用的方法,如 GET、POST, 默认是Get -
headers: 请求的头信息,比如可以在里面设置Token、设置content-type类型 -
credentials: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始,这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例 -
mode : 请求的模式,如 cors、 no-cors 或者 same-origin(默认值)
-
body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息 -
cache: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached
-
redirect : 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual
-
referrer : 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client
-
referrerPolicy : 指定了HTTP头部referer字段的值。可能为以下值之一: no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url
-
integrity : 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)
分析总结:
- fetch发送请求 默认是不发送cookie 的,不管是同域还是跨域;因此对于那些需要权限验证的请求就可能无法正常获取数据,这时可以配置其
credentials项,其有3个值:- omit : 默认值,忽略cookie的发送
- same-origin : 表示cookie只能同域发送,不能跨域发送
- include : cookie既可以同域发送,也可以跨域发送
PS:fetch默认对服务端通过Set-Cookie头设置的cookie也会忽略,若想选择接受来自服务端的cookie信息,也必须要配置 credentials 选项
-
fetch不支持超时timeout处理 -
fetch不支持JSONP
-
与XHR2一样,fetch也是支持跨域请求的,只不过其跨域请求做法与XHR2一样,需要客户端与服务端支持;另外,fetch还支持一种跨域,不需要服务器支持的形式,具体可以通过其
mode的配置项来说明。- same-origin : 该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。
- cors : 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求不需要后端额外的CORS支持;其对应的response type为cors。
- no-cors : 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;这也是fetch的特殊跨域请求方式;其对应的response type为opaque。(重点!!!)
特别注意:no-cors该模式允许浏览器发送本次跨域请求,但是不能访问响应返回的内容(能访问通接口,但是不能拿到返回值),这也是其response type为opaque透明的原因。
7.4、网络请求错误
- 根据上面的通用格式,错误肯定是
catch中处理,但是 fetch返回的promise对于404、415、500这些错误是获取不到的 ,进入不到catch,catch仅能获取由于网络延迟错误,所以这里需要再次封装一下,获取这些状态,进行throw抛出,让其进入catch即可fetch('http://jsonplaceholder.typicode.com/users') .then((response) => { if (response.status >= 200 && response.status < 300) { return response.text(); } const error = new Error(response.statusText); error.response = response; throw error; //检测到报错会进入到catch中 }).then((data) => { console.log(data); }).catch((err) => { console.log('reject:', err); }); - throw 抛出的错误会走 catch() 方法
7.5、async 与 await
-
async 与 await 同时出现,如果只用了async异步没用await,那么会出现用空内容给变量赋值的情况
-
与promise一样都是非阻塞的
const requestData = async () => {
const response = await fetch('http://jsonplaceholder.typicode.com/users');
//通过 throw 手动抛出错误
if (response.status === 200) {
throw new Error('无法获取数据');
}
const userData = await response.json();
return userData;
}
requestData().then((data) => {
console.log(data);
})
8、本地存储
8.1、本地数据增删改查
//存储
localStorage.setItem('myName','lz');
localStorage.mySex = 'male';
//获取
const name = localStorage.getItem('myName');
const sex = localStorage.mySex;
console.log(name,sex);
//删除
localStorage.removeItem('myName');
localStorage.clear();
8.2、格式转换
JSON.stringify(): 将json数据转换为字符串(方便存到本地)JSON.parse(): 将字符串转换为json数据(从本地获取使用)
9、ES6
9.1、rest参数、spread语法
- rest参数 : 可以将不确定数量的参数装入数组中作为参数
- spread语法 : 将数组内容拆散
- 使用
...变量名方式使用这两种,分散内容会被合成数组,集合类型会被拆分(新创建内容)
//rest参数
const double = (...nums) => {
console.log(nums);
return nums.map((num) => num *2);
};
const result = double(1,2,3,4,5,6,7,8);
console.log(result);
//spread语法(数组)
const users = ['张三','李四','王五'];
const members = ['熊大','熊二',...users];
console.log(members);
//spread语法(对象)
const people = {'name' : 'lz', age : 18, job : 'teacher'};
//将对象进行拷贝拆散,并扩展了location内容
const peopleClone = {...people, location: 'beijing'};
console.log(peopleClone);
9.2、Set() : 集合
- 使用
.add()添加元素、.delete()删除元素、.forEach()遍历 - 数组允许重复数据,
Set集合不能有重复数据,因此可以利用该特性来过滤重复数据
const users = ['张三','李四','王五','张三'];
//利用spread语法将Set集合拆到数组中
const uniqueUsers = [...new Set(users)];
console.log(uniqueUsers);
9.3、symbol类型
- 数据类型中,
基本类型属于原始类型、Object都属于引用类型,symbol属于原始类型 - symbol无法创建2个相同的对象,即使构建相同,因此每个symbol都是唯一的
const user = {};
const symbolOne = Symbol('user');
const symbolTwo = Symbol('user');
//不会覆盖,因为symbol作为key是不相同的
user[symbolOne] = 'one';
user[symbolTwo] = 'two';
console.log(user);
//打印结果
{Symbol(user): 'one', Symbol(user): 'two'}