深拷贝和浅拷贝
深拷贝:会开辟新的一个栈,对象属性的改变不会影响原数据
浅拷贝:共用同一个存储地址,对象属性的改变会影响原数据
手写深拷贝
function deepClone(obj={}){
if(obj !== 'object' || obj== null){
//obj为null 或者不是对象和数组时,直接返回
return obj
}
let result
if(result instanceof Array){
result=[]
}else{
result={}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
原型和原型链
Promise
promise的三种状态:pending、resolved,rejected
promise的状态变化:pending–>resolved 或 pending–>reject
promise的状态和then catch
- pending 不会触发任何 then catch 回调
- 状态变为 resolved 会触发后续的 then 回调
- 状态变为 rejected 会触发后续的 catch 回调
.then正常返回resolved,里面有报错就返回rejected
.catch正常返回resolved,里面有报错就返回rejected
如何理解这两句话的意思呢?可参考以下代码理解
Promise.resolve().then(() => { // 返回 rejected 状态的 promise
console.log(1)
throw new Error('erro1')
}).catch(() => { // 返回 resolved 状态的 promise
console.log(2)
}).then(() => {
console.log(3)
})
async/await和Promise
- async/await 解决了异步回调
- 执行async函数,返回的是Promise对象
- await相当于Promise的then
- try…catch可捕获异常,代替了Promise的catch
//打印的顺序是什么?(await后面的内容相当于异步,执行顺序先同步后异步)
async function async1 () {
console.log('async1 start') //2
await async2()
console.log('async1 end') // 5 关键在这一步,它相当于放在 callback 中,最后执行
}
async function async2 () {
console.log('async2') //3
}
console.log('script start') //1
async1()
console.log('script end') //4
/**-------分割--------*/
!(async function () {
const async3 = Promise.reject('some err')
try {
const res = await async3
console.log(res)
} catch (ex) {
console.error(ex)
}
})()
宏任务和微任务
宏任务:setTimeout、 setInterval、DOM事件、Ajax
微任务:Promise、async/await
区别:(微任务执行早于宏任务)
宏任务:DOM 渲染后再触发
微任务:DOM 渲染前会触发
微任务:ES 语法标准之内,JS 引擎来统一处理。即,不用浏览器有任何关于,即可一次性处理完,更快更及时。
宏任务:ES 语法没有,JS 引擎不处理,浏览器(或 nodejs)干预处理。
手写简版Ajax
function ajax(url){
const p=new Promise((resolve,reject)){
const xhr=new XMLhttpRequest()
xhr.open('GET',url,true) //ture异步,false同步
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
if(xhr.status===200){
resolve(Json.Parse(xhr.responseText))
}else if(xhr.status===404){
reject(new Error('404 not found'))
}
}
}
xhr.send(null)
})
return p
}
const url = '/data/test.json'
ajax(url)
.then(res => console.log(res))
.catch(err => console.error(err))
状态码分类以及常用状态码
- 1xx:服务器收到请求
- 2xx:请求成功,如200
- 3xx:重定向,301(永久重定向)、302(临时重定向)、304(资源未被修改)
- 4xx:客户端错误,404(资源未找到)、403(无权限)
- 5xx:服务端错误 如500 , 504(网关超时)
Http缓存(强制缓存和协商缓存)
协商缓存的两种资源标识对比(Etag比Last-Modified更精准)
**
综上所述
**
性能优化(空间换时间)
减少资源体积:压缩代码
减少访问次数:缓存、SSR服务器端渲染、合并代码
使用更快的网络:CDN
懒加载
对DOM缓存
防抖、节流
let const var的区别
var 存在变量提升
const 常量、var&let 变量
let、const 存在块级作用域
typeof能判断哪些类型?
- 识别值类型(undefined、string、number、boolean、symbol)
- 判断函数(function)
- 识别引用类型(typeof null==='object)
防抖节流
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效 (滚动加载)
- 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时(输入框)
//节流
function throttle(fn,delay=100){
let timer=null
return function(){
if(timer){
return
}
timer=setTimeout(()=>{
fn.apply(this,arguments)
timer=null
},delay)
}
}
//节流(时间戳和定时器)
//节流
function throttle(fn,delay){
let timer=null
let startTime=Date.now()
return function(){
let currentTime=Date.now()
let remaing=delay-(currentTime-startTime)
clearIimeOut(timer)
if(remaing<=0){
fn.apply(this,arguments)
startTime=Date.now()
}else{
timer=setTimeout(fn,remaing)
}
}
}
//防抖
function debounce(fn,dealay=100){
let timer=null
return function(){
if(timer){
clearTimeout(timer)
}
timer=setTimeout(()=>{
fn.apply(this,arguments)
timer=null
},delay)
}
}