一、正则表达式
1.1、创建字符表达式
字面量的方式
var reg = /abc/
- 此时可以检测一个字符串是否有一串紧密连接在一起的abc
内置构造函数
var reg = new RegExp ("abc")
- 与上面效果相同
字面量有
text()
的方法,用于检测文字中是否含有输入的字面量
1.2、元字符-基本元字符
\d
代表着一位数字,即输入0~9之间的一位或以上的数字,写N个\d
即为N个以上\D
代表着一个非数字,即包含一个或以上,\Dk\D
这种为中间必须有k而且是非数字\s
代表着一位空白(空格 缩进 换行)有几个\s
即为有几个空白\S
代表着有一位非空白内容,有几个\S
即为有几个非空白\n
换行符\w
包含字母,数字,下划线,有几个\w
即为有几个字母,数字,下划线\W
包含非(字母,数字,下划线),有几个\W
即为有几个非(字母,数字,下划线).
任意内容(不包含换行)\
转义字符,可将上述基本元素转换成普通字符
1.3、元字符-边界符
^
开头边界符- 放在
\d
前面即^\d
,表示开头第一个字符必须是数字
- 放在
$
结尾边界符- 放在
\d
后米即\d$
,表示结尾最后一个字符必须是数字
- 放在
/^开头结尾$/
var reg = /^abc$/
- 表示开头结尾必须是abc
1.4、元字符-限定符号
*
0~多次- 加在字符后面
+
1~多次- 加在字符后面,用
exec
方法可以截取出来数字的位置与长度
- 加在字符后面,用
?
0~1- 存在0个或者1个
{n}
指定次数- 加载字符之后,限定他出现的次数,只能限定紧挨着的
{n,}
大于等于n次- 加载字符之后,限定他出现的次数,必须大于等于n
{n,m}
大于等于n小于等于m- 加载字符之后,限定他出现的次数,必须大于等于n小于等于m
1.4、元字符-特殊符号
()
整体- 将限定的字符包括起来
- 例:
/(abc){2}/
- 这个就是限定出现两次abc
|
或- 左右两边(整体)的都行
- 例:
/a|b/
- 有a或者有b都可以
[]
代表一个- 中括号内中的字符有一个即符合
- 有规律的可以用
-
来省略范围[a-z]
表示从a到z,[0-9]
表示从0到9,[a-zA-Z0-9_]
就相当于\w
- 例:
/[asdfgh]/
- 输入的内容含有一位数与中括号内的相同,就是true
[^]
取反- 取不在这个括号范围内的数值,如果输入的值在这之中就算错误
1.5、正则表达式-捕获exec
- 根据正则提取出一串字符串中的相关字符位置以及数量
- 只能提取出遇到的第一个字符串
- 捕获后返回的是一个数组
全局标识符g
- 当一次行提取多个相同类型的变量时,可以通过在正则表达式后面加上
g
然后多次调用正则表达式来逐个提取出来 - 给每个表达式加小括号后就会出现,先提取出所有大的组为数组的第0项,其次的后面的项是第0项依据正则表达式来得到的
标识符i
- 忽略大小写
- 例:
/[a-z]/i
- 没有
i
时代表着取得范围时a~z并且必须时小写,加上i
之后大写也可以提取
- 没有
1.6、正则表达式的两大特性
- 懒惰
- 可以通过全局标识符g来解决
- 贪婪
- 会将所要求提取的数据全部提取出来
- 例:
/\d{1,4}/
- 当输入的值大于或等于四时,会提取出四个数值
- 非贪婪
- 在正则表达式后加一个
?
- 例:
/\d{1,4}?/
- 只会会提取出来一个
?
对于限定范围内有效
1.7、正则与字符串方法
- replace
- 替换字符串中的某个值
var newstr = str.replace(/a/g,"*")
- 如果没有
//g
则只能提取出第一个a
- 如果没有
- search
- 查找字符串的位置
- 只能查看第一个想要查看字符的位置
- match
- 捕获内容
- 当有重复的字符的字符串中,直接通过match与正则表达式,可以直接提取并且使其成为一个数组
1.8、案例-密码强度验证
var oinput= document.querySelector("input")
var ospan= document.querySelector("span")
var reg1 = /\d/
var reg2 = /[a-z]/
var reg3 = /[!@#$%^&*()]/
oinput.oninput =function(){
this.value
var level =0
if (reg1.test(this.value)) level++
if (reg2.test(this.value)) level++
if (reg3.test(this.value)) level++
for(var i=0;i<=ospan.lenght;i++;){
ospan[i].classList.remove("active")
if(i<level){
ospan[i].classList.add("active")
}
}
}
二、this
2.1、this指向
- 是JavaScript中的一个关键字
- 谁调用this,this就指向谁(ES6 箭头函数)
- 直接查看this,它是指向全局
- 例子:
var obj = {
name : "asdf"
test : function(){
console.log("111",this.name)
}
}
obj.test()
//此时控制台出现的就是"111,asdf"
2.2、改变this指向
call
- 可以改变
call()
指向括号内部的值 - 可以传n个参数
- 执行函数,并改变this执行为函数的第一个参数
- 可以改变
apply
- 执行函数,并改变this执行为函数的第一个参数
- 支持两个参数,第二个参数是数组
bind
- 改变this执行为函数的第一个参数,不会自动执行函数
三、ES6
3.1、ES6介绍
- 我们所说的ES5和ES6其实就是在js语法的发展过程中的一个版本而已
- ECMAScript就是js的语法
- 以前的版本没有某些功能
- 在ES5这个版本的时候增加了一些功能
- 在ES6这个版本的时候增加了一些功能
- 因为浏览器是浏览器厂商生产的
- ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能
- 这个过程是需要时间的
- 所以到现在,基本上大部分浏览器都可以比较完善的支持了
- 只不过有些浏览器还是不能全部支持
- 这就出现了兼容性问题
- 所以我们写代码的时候就要考虑哪些方法是ES5或者ES6的,看看是不是浏览器都支持
3.2、ES6关键词
let
- 定义变量
- 必须先定义在使用, 使用必须在定义之后
- 一个变量名称只能定义一次
- 定义的变量只在一个块级作用域(相当于在一个大括号内)
const
- 定义常量
- 定义后不能变,并且使用comst必须赋值
3.3、案例-块级作用域
var oHeaderItems = document.querySelectorAll(".header li")
var oBoxItems = document.querySelectorAl1( ".box li")
for(let i=0; i<oHeaderItems.length; i++){
oHeaderItems[i].dataset.index = i
oHeaderItems[i].onclick = function(){
}
}
- 选项卡案例改编,let定义后可以使当前的值得以保留所以每次点击都是当前的值,而不是循环后的值
3.4、ES6的箭头函数
- 相当于将
function(){}
改变成了()=>{}
特点
- 可以省略括号(只能是只有一个形参时可以省略)
- 可以省略
{}
(只有返回值时可以省略return,只有一句代码时) - 当返回一句语句,并且是对象时,需要在大括号外面加一个括号
- 没有arguments(arguments是相当于没有形参时,但传入了参数,此时可以以数组的方式查看参数)
- 箭头函数没有this,箭头函数中的this会指向父级作用域
默认参数
在函数的形参区域先给参数定义一个值
3.5、ES6的解构赋值
- 快速的从对象和数组中获取里面的成员
- 例:
var arr = ["asd","132","12sd"]
let [x,y,z]
console.log(x,y,z)
- 交换:
var a = 10
var b = 20
var [b,a] = [a,b]
- 多维数组取值:
var arr = [1,2,[3,4,[5]]]
//想获取5,需要arr[2][2][0]
var [a,b,[c,d,[e]]] = arr
//直接取e即可
对象
- 赋值对象(对号入座)
var obj = {
name = "zhangsan"
age = 100
location:"henaN"
}
let {name , age, location:mylocation} = obj
3.6、ES6的对象简写
对象结构中,key与后面的变量相同时,可以不写变量的名称
mybtn.onclick = function(){
let usesrname = myusername.value
let password = password.value
var obj = {
username,
password
}
}
3.7、ES6展开运算符
-
...
展开运算符 -
展开数组
- 可以展开数组
var a = [1,2,3] var b = [2,3,4,5] var c = [...a...b] //此时c数组等与a与b数组合并
- 可以复制数组
arr a = [1,2,3] var b = [...a]
- 参数-实参-形参
var test = (...arr)=>{ console.log(arr) } test(1,2,3,4,5)
- 提取数组最大值
var arr = [1,2,3,4,5] var res = Math.max(...arr)
- 伪数组转换
function test(){ var arr = [...arguments] } test(1,2,3,4,5)
-
展开对象
- 合并对象
var obj1 = { name:"zhangsan" age:100 } var obj1 = { name:"zhangsan" age:100 } var obj = { ...obj1, ...obj2 } //出现相同的key时下面的会覆盖掉上面的
3.8、ES6模块化语法
-
私密不漏
- 为了防止不想被看见的函数被使用,在js文件中将想被表达的函数放在
export{}
中,以对象的方式 - 然后在原文件里的
script
里的type
中添加module
,紧接着用import{}from './module/XXX'
的 { }中加入export{}
中的方法
- 为了防止不想被看见的函数被使用,在js文件中将想被表达的函数放在
-
重名不怕
- 与上面的方法相同,如果出现了相同的函数,则会报错
-
依赖不乱
- 在哪里用函数就在哪里导入函数,可以避免未定义而提前用
四、面向对象
4.1、初始面向对象
- 首先,我们要明确,面向对象不是语法,是一个思想,是一种 编程模式
- 面向: 面 (脸) ,向 (朝着)
- 面向过程: 脸朝着过程 =》关注着过程的编程模式
- 面向对象:脸朝着对象=》关注着对象的编程模式实现一个效果
- 实现一个效果
- 在面向过程的时候,我们要关注每一个元素,每一个元素之间的关系,顺序,。。。
- 在面向过程的时候,我们关注的就是找到一个对象来帮我做这个事情,我等待结果
- 我们以前的编程思想是,每一个功能,都按照需求一步一步的逐步完成
4.2、创建对象函数的方式
- 工厂函数:
function createObject(name){
var obj = {}
obj.name = name
//if(name==XXX){执行XXX}
onj.matical = []
return obj
}
var obj1 = createObject('shaokao')
- 自定义函数
function createObject(name){
this.name = name
this.martical = []
this.coke = function(){
}
}
var obj2=new createObject("第三次")
4.2.1、构造函数的注意事项
-
首字母大写
- 例:
function CreateObject(){}
-
构造函数中不写
return
-
构造函数可以当成不同函数用,不过里面加了this会指向window
-
this指向
function createObject(name){
this.name = name
this.martical = []
this.coke = function(){
}
}
new CreateObj()//new过程 == 实例化这个过程,实例化后,,this指向实例化对象
4.3、面向对象原型
概念:
- 在典型的 OOP 的语言中(如 Java),都存在类的概念,类就是对象的模板,对象就是类的实例,但在 ES6之前, JS 中并没用引入类的概念。
- ES6, 全称 ECMAScript 6.0 ,2015.06 发版。但是目前浏览器的 JavaScript 是 ES5版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。
- 在 ES6之前 ,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征。
对象原型__proto__
- 对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。
- __proto__对象原型和原型对象prototype是等价的。
- __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
4.4、面向对象选项卡
<head>
<style>
*{
margin:0;
padding:0;
}
ul{
list-style: none;
}
.header{
dispLay: flex;
width:500px;
}
.header li {
flex:1;
height: 50px;
line-height: 50px;
text-align: center;
border:1px solid black;
}
.box {
position: relative;
height: 200px;
}
.box li {
position: absolute;
left:0;
top:0;
width: 500px;
height: 200px;
background-color:yellow;
display:none;
}
.header .active{
background-color: red;
}
.box .active{
dispLay: block;
}
</style>
</head>
<body>
<div class="container1">
<ul class=" header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<div class="container2">
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<script>
function Tabs(select,type){
var container = document.querySelector(select)
this.oHeaderItems = container.querySelectorAll(".heraer li")
this.oBoxItems = document.querySelectorAl1( ".box li")
this.type = type
this.change()
}
Tabs.prototype.change = function(){
for(let i=0; i<oHeaderItems.length; i++){
this.oHeaderItems[i].addEventListener(type,()=>{
var index =i
for(var m=0;m<oHeaderitems.length; m++){
this.oHeaderItems[m].classList.remove("active")
this.oBoxItems[m].classList.remove( "active")
}
this.oHeaderItems[index].classList.add( "active")
this.oBoxItems [index].classList.add ( "active")
})
}
}
new Tabs(".container1","click")
new Tabs(".container2","mouserover")
</script>
</body>
4.5、class类
cLass createobj {
//构造器函数
constructor( name){
this.name =name
}
}
4.6、继承
- 构造函数继承
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.say = function(){
console.log(this.name,this.age)
}
function student(name,age,classroom){
Person.call(this,name,age)
this.classroom = classroom
}
- 原型继承
student.prototype = new Person()
- 组合继承
构造函数继承+原型继承
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.say = function(){
console.log(this.name,this.age)
}
function student(name,age,classroom){
Person.call(this,name,age)
this.classroom = classroom
}
student.prototype = new Person()
var obj1 = new student("lu",18,474)
console.log(obj1)
obj1.say()
4.8、继承案例
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<img src="">
<ul></ul>
</div>
<script>
var data1 = {
title: "体育",
list:["体育-1","体育-2","体育-3"]
}
var data2 = {
title:"综艺",
url:""
list:["综艺-1","综艺-2","综艺3"]
}
function CreateList(select,data={}) {
this.ele = document.queryselector(select)
this.title = data.title,
this.list = data.list
}
CreateList.prototype.render = function () {
//渲染页面
var h1 = this.ele.querySelector("h1")
var ul = this.ele.querySelector("ul")
// console.log(h1,ul)
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}
var obj1 = new CreateList( ".box1", data1)
obj1.render()
function CreateImgList(select,data){
CreateList.call(this,select,data)
this.imgUrl = data.url
}
CreateImgList.prototype = new CreateList()
CreateImgList.prototype.enhenceRender = function(){
this.render()
var img = this.ele.querySelector("img")
img.src = this.imgUrl
}
var obj2 = new CreateImgList( ".box2" , data2)
obj2.enhenceRender()
<script>
4.9、ES6继承
//父类
class Person{
constructor(name,age){
this.name = name
this.age = age
}
say(){
console.log("hello")
}
}
//子类
//extends继承
class Student extends Person{
constructor(name,age,grade){
super(name,age)
//super相当于Person.call(this,name,age).而且super必须写到constructor里面的第一行
this.grad = grade
}
//直接可以改变Parson里面的方法使自己使用
say(){
super.say()//调用父元素的say()使其不会被覆盖
document.write("bjsad")//修改say()方法,将其覆盖,若加上super就不会被覆盖
}
}
var obj = new Student("asd",100,100)
console.log(obj.grad)
obj.say()
五、初识前后端交互
5.1、ajax
AJAX 的优势
- 不需要插件的支持,原生js 就可以使用
- 用户体验好(不需要刷新页面就可以更新数据)
- 减轻服务端和带宽的负担
- 缺点: 搜索引擎的支持度不够,因为数据都不在页面上,搜索引擎搜索不到
AJAX 的使用
- 在js 中有内置的构造函数来创建 ajax 对象
- 创建 ajax 对象以后,我们就使用 ajax 对象的方法去发送请求和接受响应
创建步骤:
- 创建XHR ==>new XMLHttpRequest()
- 配置open(请求方式,请求地址,是否同步)
- send发出
- 接受数据,创造一个事件
ajax状态码 200 ok 404 error
- ajax 状态码-
xhr.readyState
- 是用来表示一个 ajax 请求的全部过程中的某一个状态
readyState === 0
:表示未初始化完成,也就是open
方法还没有执行readyState ===1
:表示配置信息已经完成,也就是执行完open
之后readystate === 2
: 表示send
方法已经执行完成readystate ===
3 :表示正在解析响应内容readystate ===
4 :表示响应内容已经解析完毕,可以在客户端使用了
- 这个时候我们就会发现,当一个 ax请求的全部过程中,只有当
readystate === 4
的时候,我们才可以正常使用服务端给我们的数据 所以,配合 http 状态码为 200 ~ 299 - 一个ajax 对象中有一个成员叫做 xhr.status这个成员就是记录本次请求的 http
- 状态码的两个条件都满足的时候,才是本次请求正常完成
var xhr = new XMLHttpRequest()
// ip:js%E5%AE%9E%E6%88%98%E7%BB%83%E4%B9%A0
xhr.open("GET","http://127.0.0.1:5500/js%E5%AE%9E%E6%88%98%E7%BB%83%E4%B9%A0/01.text")
xhr.send()
//当后端与前端接上头后执行该函数
xhr.onreadystatechange = function(){
// console.log("edkw");
if(xhr.readyState===4 &&xhr.status === 200){
console.log("此时已经加载完毕");
}else if(xhr.readyState === 4 &&xhr.status===404){
console.log("没有找到这个对象");
}
}
//两种区别为:onload判断一次,而onreadstatechange判断四次
xhr.onload = function(){
console.log(xhr.responseText)
if(xhr.status==200){
document.write(xhr.responseText)
}else if(xhr.status===404){
console.error("没有找到这个页面")
location.href ="404.html
}
}
readyStateChange
- 在ajax对象中有一个事件,叫做readystatechange事件
- 这个事件是专门用来监听ajax对象的readystate值改变的的行为
- 也就是说只要readystate的值发生变化了,那么就会触发该事件
- 所以我们就在这个事件中来监听ajax的readystate是不是到4了
const xhr = new XMLHttpRequest(
xhr.open( 'get', './data.php ')
xhr.send()
xhr.onreadystatechange = function(){
//每次readystate改变的时候都会触发该事件
//我们就在这里判断readystate的值是不是到4
//并且 http的状态码是不是200 ~ 299
if (xhr.readystate === 4&&/^2\d{2|S$/.test(xhr.status)) {
//这里表示验证通过
//我们就可以获取服务端给我们响应的内容了}
```
}
}
5.2、案例:ajax
JavaScript部分
<ul id="malist"></ul>
<button id="btn">lisy</button>
<script>
btn.onclick = function(){
var xhr = new XMLHttpRequest()
// ip:js%E5%AE%9E%E6%88%98%E7%BB%83%E4%B9%A0
xhr.open("GET","http://127.0.0.1:5500/js%E5%AE%9E%E6%88%98%E7%BB%83%E4%B9%A0/data.json")
xhr.send()
//当后端与前端接上头后执行该函数
xhr.onreadystatechange = function(){
// console.log("edkw");
if(xhr.readyState===4 && xhr.status === 200){
console.log("此时已经加载完毕");
var jsondata = JSON.parse(xhr.responseText)
rader(jsondata)
}else if(xhr.readyState === 4 && xhr.status===404){
console.log("没有找到这个对象");
}
}
function rader(jsondata){
var html = jsondata.data.list.map(item=>`
<li>
<img src="${item.imageUrl}"/>
<div>${item.name}</div>
</li>
`)
malist.innerHTML = html.join('')
}
}
json部分
{
"data":{
"list":[
{
"namne":"1111",
"imageUrl":"https://ts1.cn.mm.bing.net/th?id=ORMS.7bf3e9347df69e68f66692e0f32f7bc9&pid=Wdp&w=612&h=304&qlt=90&c=1&rs=1&dpr=1.25&p=0"
},
{
"namne":"1111",
"imageUrl":"https://ts1.cn.mm.bing.net/th?id=ORMS.7bf3e9347df69e68f66692e0f32f7bc9&pid=Wdp&w=612&h=304&qlt=90&c=1&rs=1&dpr=1.25&p=0"
},
{
"namne":"1111",
"imageUrl":"https://ts1.cn.mm.bing.net/th?id=ORMS.7bf3e9347df69e68f66692e0f32f7bc9&pid=Wdp&w=612&h=304&qlt=90&c=1&rs=1&dpr=1.25&p=0"
}
]
}
}
5.3、ajax同步异步
通过里面的第三个参数判断
xhr.open("GET","地址",true)
true
表示异步请求:表示会进行后面的函数,等返回值调回来的时候跟着回去
false
表示同步请求:要等到返回的数据回来过后才会执行后面的代码,所以容易造成数据的堵塞
5.4、ajax的请求方式
get 偏向获取数据
post 偏向提交数据
put 偏向更新(全部)
delete偏向删除信息
patch 偏向部分修改
- get
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType='json'
xhr.open('GET','http://127.0.0.1:8080/server-json /*?(传参位置,可以获取想得到的数据,如果不加就是全部取出 例:username=ximen)*/ ')
xhr.send()
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
if(xhr.status >= 200 ){
console.log(xhr.response);
}
}
}
- post
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType='json'
xhr.open('POST','http://127.0.0.1:8080/server-json')
xhr.send()
xhr.onreadystatechange=function(){
if(/^2d{2|$/.test(xhr.status){
if(xhr.status >= 200 ){
console.log(JSON.parse(xhr.responseText));
}
}
//如果是POST形式的需要添加send在后面
//支持 name=Kerwin&&age=100的方式
//还支持{"name":"asd"}的方式
xhr.setRequestHeader( "content-Type","application/-www-form-urlencoded")//name=kerwin&age=100
xhr.send(`username=gangdaner&password=123`)
xhr.setRequestHeader( "content-Type","application/json")//json字符串方式
xhr.send ( JSON.stringify({
username: "ximen",
password: "789"}))
}
- put
xhr.responseType='json'
xhr.open('PUT','http://127.0.0.1:8080/server-json/1')
xhr.send()
xhr.onreadystatechange=function(){
if(/^2d{2|$/.test(xhr.status){
if(xhr.status >= 200 ){
console.log(JSON.parse(xhr.responseText));
}
}
xhr.setRequestHeader( "content-Type","application/-www-form-urlencoded")//name=kerwin&age=100
xhr.send(`username=111111`)
xhr.setRequestHeader( "content-Type","application/json")//json字符串方式
xhr.send ( JSON.stringify({username: "111",)
}
- patch
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType='json'
xhr.open('PATCH','http://127.0.0.1:8080/server-json/2')
xhr.send()
xhr.onreadystatechange=function(){
if(/^2d{2|$/.test(xhr.status){
if(xhr.status >= 200 ){
console.log(JSON.parse(xhr.responseText));
}
}
//支持 name=Kerwin&&age=100的方式
//还支持{"name":"asd"}的方式
xhr.setRequestHeader( "content-Type","application/-www-form-urlencoded")//name=kerwin&age=100
xhr.send(`username=adasdasd`)
xhr.setRequestHeader( "content-Type","application/json")//json字符串方式
xhr.send ( JSON.stringify({username: "asdasda"}))
}
- delete
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType='json'
xhr.open('DELETE','http://127.0.0.1:8080/server-json/1')
xhr.send()
xhr.onreadystatechange=function(){
if(/^2d{2|$/.test(xhr.status){
if(xhr.status >= 200 ){
console.log(JSON.parse(xhr.responseText));
}
}
send()
}
5.5、ajax封装
function queryStringify(obj){
let str = ''
for (let k in obj)str += `${k}=${obj[k]}&`
return str.slice(0,-1)
}
function ajax (options){
let defaultoptions = {
ur1:"http://1ocalhoscct:3000/users",
method:"GET",
async:true ,
data:{
username : "kerwin",
password:"123"
},
headers:{},
success:function(res){
console.log(res)
}
error:function(err){
console.log(err)
}
})
5.6、回调地狱问题
- 当一个回调函数嵌套一个回调函数的时候·就会出现一个嵌套结构
- 当嵌套的多了就会出现回调地狱的情况·比如我们发送三个ajax请求
- 第一个正常发送
- 第二个请求需要第一个请求的结果中的某一个值作为参数
- 第三个请求需要第二个请求的结果中的某一个值作为参数
5.7、Promise封装ajax
<script>
封装 ajax
function ajax(options) {
let defaultoptions = {
url: "",
method: "GET",
async: true,
data: {},
headers: {
"content-type":"application/x-www-form-urlencoded"
},
success: function () { },
error: function () { }
}
let { url, method, async, data, headers, success, error } = {
...defaultoptions,
...options
}
</script>
5.8、fetch
用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response对象。当遇到网络错误时,fetch() 返回的 promise 会被 reject,并传回 TypeError。成功的 fetch()检查不仅要包括 promise 被 resolve,还要包括 Response.ok 属性为 true。HTTP 404状态并不被认为是网络错误。
var username = "kerwin"
fetch(` http:// localhost:3000/users111?username=$ {username} `)
.then((res)=>{
console. log(res)
if(res.ok){
return res.json()
}else{
//拒绝
return Promise.reject(
}
cookie
<script>
//cookie 本地存储
// 存cookie
savebtn.onclick = function(){
//路径设置
// document.cookie = "username=xiaoming;path=/155-cookie/aaa"
document.cookie = "age=18"
//过期时间设置
var date = new Date()
date.setMinutes(date.getMinutes()+10)
document.cookie = `username=kerwin;expires=${date.toUTCString()}`
}
getbtn.onclick = function(){
console.log(getCookie("age"))
}
function getCookie(key){
var str = document.cookie
var arr = str.split("; ")
// console.log(arr)
var obj = {}
for(var i=0;i<arr.length;i++){
var subArr = arr[i].split("=")
// console.log(subArr)
obj[subArr[0]] = subArr[1]
}
// console.log(obj)
return obj[key]
}
delbtn.onclick = function(){
var date = new Date()
date.setMinutes(date.getMinutes()-1)
document.cookie = `username=111;expires=${date.toUTCString()}`
document.cookie = `age=111;expires=${date.toUTCString()}`
}
</script>
josnp
注:
- 后端接口形式必须**(),需要后端配合
- jsonp 缺点
onload 删除sciprt标签
只能get请求,不能post put delete
mybtn.onclick = function(){
var oscript = document.createElement( "script")
oscript.src="01.txt”//未来地址
document.body . appendchild(oscript)
}
5.9、闭包
函数内部返回一个函数,被外界所引用。
这个内部函数就不会被销毁回收。
内部函数所用到的外部函数的变量也不会被销毁
5.10、闭包案例
求索引值下标
法一:(闭包)
var oli = document.querySelectorAl1("li")
for (var i = 0; i < oli.length; i++) {
oli[i].onclick = (function (index) {
return function () {
console.log(11111, index)
}
})(i) //匿名自执行函数
}
法二:(ES6)
var oli = document.querySelectorAl1("li")
for(let i=0;i<oli.length;i++){
oli[i].onclick =function(){
console.log(i)
}
}