常见响应码
101:协议升级,当想升级到websocket协议时, 客户端发送upgrade:websocket,connection:keep-alive,Upgrade,如果服务端同意协议升级,会返回101 websocket protocol handshake 表示升级成功。
200 ok:表示成功返回响应
206:当客户端使用range请求部分数据时,服务端返回206 partial content,表示传来了部分数据。并返回响应头content-range:bytes 范围。。。
301:使用get请求方式,永久重定向
302:使用get请求方式,临时重定向,不用缓存。
303:不表示资源变迁,二是用户表单提交后返回新的内容
304:使用缓存,根据客户端发送的If-None-Match、If-Modified-Since
307:临时重定向,使用原请求方式和包体
308:永久重定向,使用原请求方式和包体
403 Forbidden:服务端无权限
404 Not Found:服务端没有找到资源
416 Range Not Satisfieable客户端请求的范围不满足实际资源的大小
localStorage存满了怎么办
1、使用try...catch
向localStorage中setItem("","")
,如果出现错误存不进去,使用localStorage.clear()
清除本地存储
2、使用postMessage将数据存在另一个域的localStorage里
postMessage:
跨域实现localStorage共享
在child.html中:window.parent.postMessage(data,origin)
,实现向不同域传送数据,data需要使用JSON.stringify()
方法对对象参数序列化。
在main.html中:window.addEventListener('message', function(e) {})
,监听message事件,e.data中获取child.html传来的数据。
节流throttle、防抖debounce:
function throttle(fn,ms){
var timer=null
return function(){
var context=this
var args=arguments
if(!time){
timer=setTimeout(()=>{
fn.apply(context,args)
},ms)
}
}
}
function debounce(fn,ms){
var timer=null
return function(){
var context=this
var args=arguments
clearTimeout(timer)
timer=setTimeout(()=>{
fn.apply(context,args)
},ms)
}
}
调用:
document.getElementsByClassName("dv")[0].addEventListener("click",throttle(fn,1000))
//传入节流防抖的函数,和时间间隔。返回throttle中return的函数,当触发事件时执行函数。多次触发,此时下一个函数的timer已经有值,不符合if(!time)的条件。这里用到了闭包,函数外部可以访问函数内部的变量。
document.getElementsByClassName("dv")[0].addEventListener("click",debounce(fn,1000))
ES6中的内容:
var let const:
let、const:不能重复声明,会产生块级作用域,没有this指向,没有变量提升。变量声明之前,变量都是不可用的,“暂时性死区”
let x=1
const y=2
var z=3
console.log(window.x)//undefined
console.log(window.y)//undefined
console.log(window.z)//undefined
解构赋值
function move({x,y}={x:0,y:0}) {
return [x,y]
}
console.log(move({x:3,y:8}))//[3,8]
console.log(move({x:3}))//[3,undefined]
console.log(move({}))//[undefined,undefied]
console.log(move())//[0,0]
扩展运算符
Math.max(...arr)
数组的方法
.keys()、values()、entries(),fill()、includes()
箭头函数:
this指向为定义时所在的对象
没有argments
没有构造函数,不能使用new命令
对象的方法
Object.keys()、values()、entries()、.assign(),
数据类型Symbol
数据结构Set、Map
Promise
async、await
Class
apply、call、bind
改变this指向
call:第一个参数为obj,后面的参数为传入的参数
apply:第一个参数为obj,第二个参数为数组,里面为传入的参数
bind:返回一个函数,第一个函数为obj【新的this指向】,第二个参数为数组
function bind(obj){
var that=this
var context=[].shift.call(arguments)//arguments不是数组,需要使用数组的方法时要使用call
var args=[].slice.call(arguments)
return function(){
that.apply(context,args.concat([].slice.call(argments)))
}
}
数据类型:null,undefined,string,number,boolean,symbol,object
typeof:判断数据类型,结果可能为string,number,boolean,undefined,object,function
instanceof:根据原型链,判断实例是否属于该引用类型的实例,可以判断Object、Array、Date、RegExp、Function
原型链:
实例对象和对应构造函数的原型对象的关系:每个构造函数都一个原型对象,即prototype对象。prototype对象里面有一个指向构造函数的指针constructor,还有一些方法。实例对象的__proto__属性指向构造函数的原型对象。
new过程:
1、创建一个新的对象
2、建立新对象__proto__和构造函数原型对象prototype的关系,将this指向构造函数的作用域
3、运行构造函数内部代码
4、返回这个新对象return this
hasOwnPrototype:判断实例对象上是否有这个属性。
继承:
1、
function Father(){
...
}
function Child(){
...
}
Child.prototype=new Father()//原型链继承,实现原型对象上的属性和方法
2、
function child(){
Father.call(this,"","")//借由构造函数继承,实现实例对象属性继承
this.age=12
}
3、组合继承,结合原型链继承原型对象上的属性和方法,借由构造函数实现实例对象属性继承
function child(){
Father.call(this,"","")//借由构造函数继承,实现实例对象属性继承
this.age=12
}
child.prototype=new Father()
4、
Class Father{
constructor(){
this.xxx//定义在constructor中的属性为实例对象上的属性
}
}
Father.prototype.x=1
Father.prototype.y=2
Class Child extends Father{
constructor(x,y,color){
super(x,y)//指向原型对象,定义在实例对象上的方法或属性无法通过super调用
this.color:color
}
toString(){
}
}
10进制转8进制:
var a=10
a.toString(8)//"12"
function toEight(x){
var res=[]
var str=""
while(x<0){
res.push(x%8)
x=parseInt(x/8)
}
while(res.length>0){
str+=res.pop()
}
return str
}
客户端保持登录状态
由于http无状态,可以采用cookie、session、localStorage、sessionStorage保存用户的登录状态
1、cookie和session
客户端第一次请求服务端时,服务端会把客户端的登录信息存在session里,并将sessionID传给客户端,通过set-Cookie响应头,传递cookie信息。当客户端第二次请求服务端时,会携带Cookie请求头。服务端通过sessionID获取用户的登录信息,这样用户就可以直接访问,不用登陆
2、token和localStorage
客户端第一次请求服务端,输入用户信息,服务端通过验证后,会给客户端返回Token安全令牌(随机字符串),并返回给客户端。可以将token存在localStorage、sessionStorage中,当再次ajax请求时,通过设置请求头Authentication【授权书】携带token,服务端获取token并验证,最后返回数据。
vue项目中,可以通过vuex来实现对localStorage中token的获取、更改。
闭包的作用:
1、模仿块级作用域,匿名自调用函数属于闭包,里面定义的变量只有闭包内不可用,避免全局环境污染。
2、延长变量作用域链,函数内部return一个匿名函数,这个匿名函数也是闭包。使函数外部也可以访问函数内的变量。连接函数内部和函数外部的桥梁
手写jsonp:
function jsonp(url,data){
return new Promise(function(resolve,reject){
var script=document.createElement("script")
var callback="callback_"+new Date().getTime()
window[callback]=function(data){
resolve(data)
document.body.removeChild(script)
}
var str=""
for(let key in data){
str+=`${key}=${data[key]}&`
}
var src=url+"?"+str+"callback="+callback//url?a=1&b=2&callback=callback_213
script.src=src
document.body.appendChild(script)
})
}
jsonp(url,{....}).then((data)=>{
console.log(data)
})
vue响应式
function Observer(obj){
if(!isObject(obj)){
throw new TypeError()
}
Object.keys(obj).forEach(key=>{
var dep=new Dep()
Object.defineProperty(obj,key,{
get(){
dep.depend()//收集订阅者
return obj[key]
},
set(newvalue){
var value=obj[key]
if(newvalue!==key){
obj[key]=newvalue
dep.notify()//通知所有订阅值
}
}
})
})
}
class Dep{
constructor(){
this.subscriber=new Set()
}
notify(){
this.subscribers.map(i=>i())
},
depend(){
if(activeUpdate){
this.subscribers.add(activeUpdate)
}
}
}
var activeUpdate
function autorun(updata){//传入updata的函数
function wrap(){
activeUpdate=wrap
updata()
activeUpdate=null
}
wrap()
}