正则表达式
构造语法
-
字面量
var reg=/abc/
:这个例子检验必包含abc字母且紧密连在一起 -
内置构造函数
var rge=new RegExp("abc")
同义
检验方法
reg.test(myinput.value)
返回值是true或false
捕获方法
exec()
:能捕获符合条件的片段 返回值是数组或空值 只能捕获遇到的第一个,因为他不会记住捕获后的的下标 对于限定符,捕获方法开启贪婪特性,会取出最大限度。我们可以在限定符后加上?
来让其取最少次数
标识符
解决捕获的懒惰
var datestr="time is 2029-01-01 12:20:20 to 2019-11-01 12:20:20"
var reg =/\d{4}-\d{1,2}-\d{1,2}/g
var newdatestr1=reg.exec(datestr)//第一个符合条件的
var newdatestr2=reg.exec(datestr)//第二个符合条件的
var newdatestr3=reg.exec(datestr)//null值
console.log(newdatestr1.split[0]("-").jion("/"))//返回值是数组,所以将下标为0的数组元素即字符串分割成一个数组再转换为字符串
console.log(newdatestr2.split[0]("-").jion("/")
var reg =/(\d{4})-(\d{1,2})-(\d{1,2})/g
//加小括号后会添加一个单独捕获的功能
var newdatestr1=reg.exec(datestr)//第一个符合条件的
var newdatestr2=reg.exec(datestr)//第二个符合条件的
//数组第一个元素是捕获全体,后面的是捕获括号内的内部
可以解决字符串中的match,replace方法同样具有的懒惰性,注意要用到正则表达式
-
字符串的match方法
var datestr="time is 2029-01-01 12:20:20 to 2019-11-01 12:20:20" console.log((datestr.match(/\d{4}-\d{1,2}-\d{1,2}/g)) //好处是这个方法直接将拿到的两个数据放在同一个数组
-
i:捕获不分大小写
元字符
表示一类字符
常见释义
\d
:包含数字\d\d
:包含两位数字\D
:包含非数字\D\D
:包含两位非数字\Dk\D
:两位非数字夹着一个k\s
:包含空白(空格,缩进,换行都可以)\S
:包含非空白\w
:包含字母、数字、下划线\W
:包含非字母、数字、下划线\W\W
:包含两位非字母、数字、下划线.
:任意内容(只有换行符的除外)\任意字符
:转义字符,反斜杠后面的内容会被转义为固定字符,而不是当做元字符翻译
边界符
^元字符
:开头必须是元字符类型$元字符
:结尾必须是元字符类型
限定符
限定字符类型出现次数,元字符加在对应限定符前面,其中限定符只能修饰紧挨着它前面的元字符(边界符也是)
*
:任意次数+
:至少出现一次?
:0~1次{n}
:指定次数{n,}
:>=n{n,m}
:n~m
特殊符号
-
()
:将元字符装为一个整体 -
|
:包含|两边的元字符中一个就可以需要注意的是:|会分别把两边所有内容看做一个整体,即必须包含两边中一个的整体
-
[n个字符]
:至少包含n个字符中的一个 -
-
:表示延伸[a-zA-Z0-9_]
=\w
[0-9]
=\d
-
[^n个字符串]
:至少不包含n个字符中的一个在[]内使用不同于边界符的意思,例如
[^abc]
检验abz也true
ES6
定义变量
-
let
-
不能在定义之前访问
-
变量不能重定义
-
块级作用域,包含if语句,switch语句等,不限于函数块
简易选项卡案例改进
·<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <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; } .box li { position: absolute; left: 0; top: 0; width: 500px; height: 200px; background-color: yellow; display: none; } /* 给第一个样式先来个激活状态 */ .header .active { background-color: orange; } .box .active { display: block; } </style> </head> <body> <ul class="header"> <li class="active">1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <ul class="box"> <li class="active">111</li> <li>222</li> <li>333</li> <li>444</li> </ul> <script> var headerItems = document.querySelectorAll(".header li") var boxItems = document.querySelectorAll(".box li") //用for循环给每li添加自定义属性标识,并且设置标题的点击事件 //用let定义,每次循环都是新的i for (let i = 0; i < headerItems.length; i++) { /* headerItems[i].dataset.index=i; */ headerItems[i].onclick = handler //点击事件函数 function handler() { //辨识点击哪个标题 var index = i //移除激活类名 for (var m = 0; m < headerItems.length; m++) { headerItems[m].classList.remove("active") boxItems[m].classList.remove("active") } //添加激活状态 headerItems[index].classList.add("active") boxItems[index].classList.add("active") } } </script> </body> </html>
-
-
const:定义后作为常量存在,不能再重新赋值,不能只定义不赋值
应用于网页中一些作为参考的数据
-
let块级作用域案例:最常用的情景
函数的默认参数
普通函数和箭头函数均适用
//当调用函数时忘记传参,会使用默认值
function test(a=1.b=2){
return a+b
}
箭头函数
-
语法:
var 变量=(0=>{})
-
只有一个形参的时候可以省略()
-
当大括号内只有一句代码或只有返回值,{}与return可以省略
var newlist =list.map(function(item){ return `<li>${item}</li>` }) //可以转化为 var newlist =list.map(item=>`<li>${item}</li>`)
当{}里面只有一个对象时,不省略{}
-
arguments:没办法用箭头函数
在函数没有形参的情况下,调用函数时传实参给函数,在函数内使用此关键字可以得到所传实参的伪数组。
var test=function(){ console.log(a,b,c) console.log(arguments[0],arguments[1],arguments[2]) //转化为真数组 console.log(Array.from(arguments)) }) test(1,2,3)
-
箭头函数的this是父级作用域的
//如果直接在计时器内用this,会指向window,所以用that在外面暂存this mytext.oninput=function(){ var that=this setTimeout(()=>{ console.log(that.value) },1000) } //箭头函数可以直接指向外面的父级元素 mytext.oninput=function(){ setTimeout(()=>{ console.log(this.value) }1000) }
-
解构赋值
快速从对象和函数中获取里面的成员
-
数组
var arr=["1","2","3"] let[x,y,z]=arr console,log(x,y,z)
-
对象
var obj={ name:"1", age:"2", location:"3" } //因为location变量名已经被window占用,不能重名,可以自己用冒号重命名 let {name,age,location:mylocation}=obj console.log(name) console.log(age) console.log(mylocation)
对象简写
当成员与成员值一样时可以只写一个
如:var obj={getname:getname}
可以写成var obj={getname}
如:var obj={getName:function(){}}
可以写成var obj={getName(){}}
展开运算符…
-
展开拼接
var a=[1,2,3] var b=[4,5,6] 拼接两数组 //conlose.log(a,concat(b)) var c=[...a,...b]
-
展开复制
var a=[1,2,3] //var b=a.slice() //var b=a.concat() var b=[...a] b[0]="ha"
-
参数-实参-形参
- 解决arguments不能用于箭头函数的问题
var test=(...arr)=>{ console.log(arguments) } test(1,2,3,4)
-
a对应1,b对应2,…arr对应[3,4,5]
而且…arr放在最后最后一个参数
var test=function(a,b...arr)=>{ console.log(arr) } test(1,2,3,4,5)
- 找出后端所传数据的最值
var arr=[1,2,3,4,5,6,7,8,9] var res=Math.max(...arr)
- 伪数组转换
function test(){ var arr=[...arguments] console.log(arr) } test(1,2,3,4,5)
案例:用户数据修改
<input type="text" id="myusername">
<input type="tel" id="myage">
<button id="btn">修改</button>
<div id="box"></div>
<script>
//后端数据
var obj = {
name: "xiaohong",
age: 100,
location: "guangdong",
id: "2154285424252"
}
//后端数据渲染
function render({name,age,location}) {
box.innerHTML = `name${name},age${age},location:${location}`
}
render(obj)
btn.onclick=function(){
var name=myusername.value
var age=myage.value
var newobj={
...obj,
name,
age
}
//重新渲染
render(newobj)
}
</script>
模块化语法
-
模块化之前的痛点
引用js文件时
- 私密代码依然会被访问
- 会出现变量名重复
- 多个js文件互相引用会出现一定的顺序依赖
-
模块化语法——私密不怕
分两步
-
外部js文件导出:
export{ a,b,c...//你想被别人导入的函数名 }
-
本文件导入:
<script type="module"> import{a,b,c...你想导入的函数名} from `文件路径` </script> 之后便可以直接调用函数
-
-
模块化语法——重名不怕
-
文件导入:
<script type="module"> import{a,重名函数 as 重命名} from `文件路径` </script> 之后便可以直接调用函数-以重命名方式
-
-
模块化语法——依赖不乱
分两步
-
在外部js文件中先引入需要的其他js文件
<import>{...}from`路径` 之后便可以直接调用函数
-
本文件导入时引入顺序可以不按顺序
-
面向对象
面向对象是一种编程思维,在这个过程中,我们需要关注每一个元素,元素之间的关系,顺序…
创建面向对象的方式
使用自定义构造函数
function 函数名(形参){执行语句}
var 变量名=new 函数名(实参)
构造函数需要要注意的
- 函数名首字母大写
- 构造函数不需写return,写了也没作用(除非返回的是复杂数据类型)
- 构造函数能当普通函数调用
- this指向
- new过程也是实例化的过程,在实例化之前,this没有指向;实例化之后,实例对象就已经生成了,无关是否赋值
面向对象的原型
对象._proto_===构造函数.prototype
- 案例:用面向对象思想渲染页面
<script>
var data1 = {
title:"体育",
list: ["体育—1", "体育—2", "体育—3"]
}
var data2 = {
title:"综艺",
list: ["综艺—1", "综艺—2", "综艺—3"]
}
//构造函数
function CreateList(select, data) {
//获取节点
this.ele = document.querySelector(select)
//赋予后端数据
this.title = data.title,
this.list = data.list
//渲染页面
this.render = function () {
var h1 = this.ele.querySelector("h1")
var ul = this.ele.querySelector("ul")
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}
}
//
var obj1 = new CreateList(".box1", data1)
obj1.render()
var obj2 = new CreateList(".box2", data2)
obj2.render()
</script>
缺点:每new一个自定义函数都会在堆内存中开辟新的空间
=》用对象原型思想渲染页面
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<ul></ul>
</div>
<script>
var data1 = {
title:"体育",
list: ["体育—1", "体育—2", "体育—3"]
}
var data2 = {
title:"综艺",
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")
//渲染页面
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}
//
var obj1 = new CreateList(".box1", data1)
obj1.render()
var obj2 = new CreateList(".box2", data2)
obj2.render()
</script>
用面对对象思想建选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<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: orange;
}
.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>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<div class="container2">
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<script>
var headerItems = document.querySelectorAll(".header li")
var boxItems = document.querySelectorAll(".box li")
//属性放在各自的
function Tabs(select, type) {
var container = document.querySelector(select)
this.headerItems = container.querySelectorAll(".header li")
this.boxItems = container.querySelectorAll(".box li")
//自己调用原形的方法
this.type = type
this.change()
}
//方法放在共用的
Tabs.prototype.change = function () {
for (let i = 0; i < this.headerItems.length; i++) {
/* headerItems[i].dataset.index=i; */
this.headerItems[i].addEventListener(this.type, () => {
//辨识点击哪个标题
var index = i
//移除激活类名
for (var m = 0; m < this.headerItems.length; m++) {
this.headerItems[m].classList.remove("active")
this.boxItems[m].classList.remove("active")
}
//添加激活状态
this.headerItems[index].classList.add("active")
this.boxItems[index].classList.add("active")
})
}
}
//可以穿第二个参数,控制事件类型
new Tabs(".container1", "click")
new Tabs(".container2", "mouseover")
</script>
</body>
</html>
es6:class构造器函数
将属性和公共方法分开
语法:
class 函数名{
constructor(){函数属性}
原型中挂的方法
}
选项卡改造
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<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: orange;
}
.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>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<div class="container2">
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<div class="container3">
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</div>
<script>
var headerItems = document.querySelectorAll(".header li")
var boxItems = document.querySelectorAll(".box li")
class MyTabs {
constructor(select, type) {
var container = document.querySelector(select)
this.headerItems = container.querySelectorAll(".header li")
this.boxItems = container.querySelectorAll(".box li")
this.type = type
this.change()
}
change() {
for (let i = 0; i < this.headerItems.length; i++) {
/* headerItems[i].dataset.index=i; */
this.headerItems[i].addEventListener(this.type, () => {
//辨识点击哪个标题
var index = i
//移除激活类名
for (var m = 0; m < this.headerItems.length; m++) {
this.headerItems[m].classList.remove("active")
this.boxItems[m].classList.remove("active")
}
//添加激活状态
this.headerItems[index].classList.add("active")
this.boxItems[index].classList.add("active")
})
}
}
}
new MyTabs(".container1", "click")
new MyTabs(".container2", "mouseover")
new MyTabs(".container3", "mouseover")
</script>
</body>
</html>
面向对象继承
构造函数继承—只能继承属性:通过在引入后强行改变this指向
原型继承—继承原型上的方法:
理解代码
function Person(name,age){
this.name=name
this.age=age
}
Person.prototype.say=function(){}
function Student(name,age,grade){
Person.apply(this,[name,age])
this.grade=grade
}
//继承person原形:但会有一些空数组形成
Student.prototype=new Person()
//为student挂上新的方法
Student.prototype.printGrade=function(){}
//覆盖原有方法
Student.prototype.say=function(){}
//增强原有方法
Student.prototype.say2=function(){
//继承原来方法
this.say()
增加的语句...
}
组合继承:构造函数继承+原型继承
ajax
拥有前后端交互不跳转链接的良好体验
前后端交互
客户端=>服务器=>数据库
基础流程
-
创建xhr
var xhr=new XMLHttpRequest()
-
配置
xhr.open("请求方式","请求地址","是否异常")
请求方式常为:GET
请求地址:http为协议名,localhost为本机域名,127.0.01为本机IP
-
发送
xhr.send()
-
接收数据,注册一个事件
ajax状态码
-
ajax的事件
-
readyStateChange:这个事件是专门用来监听 ajax 对象的
readyState
值改变的的行为,客户端与后端接上头就会执行的语句xhr.onreadystatechange=function(){` if(ajax.readystate===4/*保证前端数据齐全*/&&xhr.status===200/*确保数据正确,404表示找不到页面*/){ } }
-
onload:只有处于状态码4,请求已完成,响应已就绪的情况下,才会进入onload。
xhr.onload=function(){` if(xhr.status===200){ }else if(xhr.status===404){} }
-
-
ajax状态有5个状态
- 0:未初始化,open还没打开
- 1:配置完成
- 2:send完成
- 3、解析响应内容
- 4、解析完毕,客户端可以使用
模拟前后端案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">获取数据</button>
<ul id="mylist"></ul>
<script>
btn.onclick = function () {
var xhr = new XMLHttpRequest()
xhr.open("GET", "....")
xhr.send()
xhr.onload = function () {
if (xhr.status === 200) {
var jsondata = JSON.parse(xhr.responseText)
render(jsondata)
}
}
}
function render(jsondata) {
console.log(jsondata.data.list)
var html = jsondata.data.list.map(item => <li>
<img src="${item.imageUrl}" />
<div>${item.name}</div>
</li>)
}
</script>
</body>
</html>
ajax同步异步
-
同步:调用某个内容时,调用方等这个调用返回结果才继续往后执行,期间不执行其他语句.不推荐
-
异步:调用发出后调用者可用继续执行后面的语句
var xhr=new XMLHttpRequest()
xhr.open("GET","1.json",false)
//传true表示异步请求,false表示同步请求
xhr.send()
xhr.onload=function(){}
ajax请求方式
由后端决定
下面的例子在Preview on Web Server插件下使用,仅模仿了部分后端的功能
get:偏向获取数据
btn.onclick = function () {
var xhr = new XMLHttpRequest()
//取得话会取出全部,此时我们可以在路径后加?key=value取出部分的
xhr.open("GET", "....")
xhr.send()
xhr.onload = function () {
if (xhr.status === 200) { }
}
xhr.send()
}
post:偏向提交数据
btn.onclick = function () {
var xhr = new XMLHttpRequest()
xhr.open("POST", "....")
xhr.onload = function () {
if (xhr.status === 200) { }
}
//用这条语句表明传输格式key-value
xhr.xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
xhr.send(`username=shanzhen&password=456`)
}
//或用这条语句表明传输格式form
xhr.xhr.setRequestHeader("Content-Type","application/json")
xhr.send(JSON.stringify({
username:"ximen",
password:"789"
}))
}
put:偏向全部覆盖
btn.onclick = function () {
var xhr = new XMLHttpRequest()
//在连接后加/id表示修改谁
xhr.open("PUT", "..../1")
xhr.onload = function () {
if (xhr.status === 200) { }
}
xhr.setRequestHeader("Content-Type","application/json")
xhr.send(JSON.stringify({
username:"ximen",
password:"789"
}))
}
patch:偏向部分更新
btn.onclick = function () {
var xhr = new XMLHttpRequest()
//在连接后加/id表示修改谁
xhr.open("PATCH", "..../1")
xhr.onload = function () {
if (xhr.status === 200) { }
}
xhr.setRequestHeader("Content-Type","application/json")
xhr.send(JSON.stringify({
username:"ximen",
password:"789"
}))
}
delete:偏向删除信息
btn.onclick = function () {
var xhr = new XMLHttpRequest()
//在连接后加id表示修改谁
xhr.open("DELETE", "..../2")
xhr.onload = function () {
if (xhr.status === 200) { }
}
xhr.send()
}
…
ajax封装
代码理解:
// 封装 ajax
function ajax(options) {
let defaultoptions = {
url: "",
method: "GET",
async: true,
data: {},
headers: {},
success: function () { },
error: function () { }
}
let { url, method, async, data, headers, success, error } = {
...defaultoptions,
...options
}
if (typeof data === 'object' && headers["content-type"]?.indexOf("json") > -1) {
data = JSON.stringify(data)
}
else {
data = queryStringify(data)
}
// 如果是 get 请求, 并且有参数, 那么直接组装一下 url 信息
if (/^get$/i.test(method) && data) url += '?' + data
// 发送请求
const xhr = new XMLHttpRequest()
xhr.open(method, url, async)
xhr.onload = function () {
if (!/^2\d{2}$/.test(xhr.status)) {
error(
</span><span class="token string">错误状态码:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>xhr<span class="token punctuation">.</span>status<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">
)
return
}
// 执行解析
try {
let result = JSON.parse(xhr.responseText)
success(result)
} catch (err) {
error('解析失败 ! 因为后端返回的结果不是 json 格式字符串')
}
}
// 设置请求头内的信息
for (let k in headers) xhr.setRequestHeader(k, headers[k])
if (/^get$/i.test(method)) {
xhr.send()
} else {
xhr.send(data)
}
}
</span><span class="token string">错误状态码:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>xhr<span class="token punctuation">.</span>status<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">
ajax({
url:"http://localhost:3000/users",
method:"GET",
async:true,
data:{
username:"kerwin",
password:"123"
},
headers:{},
success:function(res){
console.log(res)
},
error:function(err){
console.log(err)
}
})
回调地狱
当回调函数互相嵌套过多时会导致。
如:
//正常发送
ajax({
url: '1',
success (res) {
// 第二个请求:需要第一个请求的结果中的某一个值作为参数
ajax({
url: '2',
data: { a: res.a, b: res.b },
success (res2) {
// 第三个请求:需要第二个请求的结果中的某一个值作为参数
ajax({
url: '3',
data: { a: res2.a, b: res2.b },
success (res3) {
console.log(res3)
}
})
}
})
}
})
es6的promise语法
专门解决回调地狱
-
语法
每一个异步事件,在执行的时候都会有三个状态:执行中 / 成功 / 失败
借助成功状态,用Promise解决回调地狱
代码理解:
new Promise(function (resolve, reject) {
ajax({
url: '1',
success (res) {
resolve(res)
}
})
}).then(function (res) {
// 发送第二个请求
return new Promise(function (resolve, reject) {
ajax({
url: '2',
data: { a: res.a, b: res.b },
success (res) {
resolve(res)
}
})
})
}).then(function (res) {
ajax({
url: '3',
data: { a: res.a, b: res.b },
success (res) {
console.log(res)
}
})
})
es7 的async/await语法
回调地狱的终极解决方案
await 一个 promise 对象,只要是一个 promiser 对象,那么我们就可以使用 async/await
来书写
-
语法
async function fn() { const res = await promise对象 }
fetch
XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱, 而且基于事件的异步模型写起来不友好。
兼容性不好 polyfill: https://github.com/camsong/fetch-ie8
cookie
cookie的特点
-
只能存储文本
-
数量限制(一般浏览器,限制大概在50条左右)
-
读取有域名限制:不可跨域读取,哪个服务器发给你的cookie,只有哪个服务器有权利读取
-
时效限制
-
会话级别:当浏览器关闭,那么cookie立即销毁,
我们也可以在存储的时候手动设置cookie的过期时间
-
路径限制:存cookie时候可以指定路径,只允许子路径读取外层cookie,外层不能读取内层。
jsonp
json 的一种使用模式,可以让网页从别的网页获取资料
同源策略规定我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )
语法:
const script = document.createElement('script')
script.src = './kerwin.txt'
document.body.appendChild(script)