HTML

  1. html语义化

  2. meta viewport
    github head

     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
    
  3. 用过什么html5标签

    header footer main article
    canvas video audio
    搜索mdn

  4. H5是什么?
    移动端页面

     1. 页面素材预加载,createJS的preloadJS
     2. 音乐加载播放技术,createJS的soundJS或H5的audio
     3. 可滑动页面,swiper.js
     4. 可涂抹擦除,canvas叠层
     5. 动态文字和图片,css3动画与js动画
     6. 填报报名 html表单
     7. 支持分享自定义的文案和图片 微信jssdk
    
     炫酷效果:egret/cocos2d/
    

CSS

  1. 盒模型
    content-box 内容区宽度
    border-box content+padding+border

  2. 实现垂直居中

    1. table自带功能

      <table>
       <tr>
           <td>内容</td>
       </tr>
      </table>
      

      2 100%高度的after before 加上inline block

      2.1 方案一

      <div class="parent">
       <span class="before"></span>
       <div class="child">内容</div>
       <span class="after"></span>
      </div>
      
      <style>
       .parent{
           text-align:center;//水平居中
           padding:10px 0;//让父元素有高度,但不必要
       }
       .child{
               display: inline-block;
               vertical-align: middle;
           }
       .before,.after{
               display: inline-block;
               hegiht:100%;
               vertical-align: middle;
           }
      </style>
      

      2.2 方案一优化版

      <div class="parent">
       <div class="child">内容</div>
      </div>
      
      <style>
       .parent{
           text-align:center;//水平居中
           padding:10px 0;//让父元素有高度,但不必要
       }
       .child{
               display: inline-block;
               vertical-align: middle;
           }
       parent::before,parent::after{
               cotent:'';
               display: inline-block;
               hegiht:100%;
               vertical-align: middle;
           }
      </style>
      

      3 postion+负margin子元素宽高的一半

      <div class="parent">
       <div class="child>内容</div>
      </div>
      <style>
       .parent {
           position: relative;
       }
      
       .child {
           position: absolute;
           width: 300px;
           height: 100px;
           top: 50%;
           left: 50%;
           margin-top: -150px;
           margin-left: -50px;
       }
      </style>
      
    2. transform: translate(-50%,-50%)

    3. flex

    4. absolute top/bottom/left/right:0;margin:auto

  3. flex属性

  4. BFC是什么
    块级格式化上下文,常见的例子有:

    1. overflow:hidden
    2. 浮动元素
    3. 绝对定位元素
    4. inline-block
    5. flex或者inline-flex

      解决了什么问题:

    6. 清除浮动
    7. 防止margin合并
  5. CSS选择器优先级

    1. 越具体优先级越高
    2. 写在后面的,覆盖写在前面的
    3. importan!最高 少用
  6. 清除浮动
    .clearfix{

     content:'';
     display:block;
     clear:both;
    

    }
    加到容器上,里面子元素浮动被清除.

  7. 重绘重排

    1. 重绘:元素外观发生改变,如元素填充颜色
    2. 重排:布局发生改变,需要重新生成布局,重新排列元素
      减少重排
       i. 脱离文档流
       ii. 避免频繁操作样式
       iii. 减少重排范围,尽量将样式加载具体元素上,而不是它的父级 
      

      JS

  8. ES6属性

  9. Promise.all Promise.race

     //Promise
    
     function xxx(){
         return new Promise(function(resolve,reject){
             setTimeout(()=>{
                 if(xxx){
                     resolve('data')
                 }else{
                     reject(new Error('error'))
                 }
             })
         }
     }
    
     //Promise.all([fn,fn2,fn3]).then(res1,res2,res3) 
     //Promise.race([fn,fn2,fn3]).then(res)
    
  10. 函数防抖,函数节流
    防抖:事件触发,假如事件在一定时间内不再触发,则调用函数

     function 防抖(fn,time){
         let timer = null;
         return ()=>{
             if(timer){
                 clearTimeout()
             }
             timer = setTimeout(()=>{
                 fn()
                 timer = null
             },time)
         }
     }
    

    节流:一段时间内只能调用一次函数

     function 节流(fn, time) {
         let doing = false;
         return () => {
             if (doing === false) {
                 doing = true;
                 fn()
                 setTimeout(() => {
                     doing = false;
                 }, time)
             }
         }
     }
    
  11. 手写ajax

     var request = new XMLHttpRequest();
     request.open('GET','url')
     request.onreadystatechange = function(){
         if(request.readyState === 4){
             if(request.status >= 200 && request.status < 300 || request.status === 304){
                 console.log(request.responseText)
             }else{
                 console.log('error')
             }
         }
     }
     request.send()
    

    用promise写ajax

     function ajax(method,data,url){
         return new Promise(function(resolve,reject){
             let request = new XMLHttpRequest()
             request.open(method,url)
             request.onreadystatechange = function(){
                 if(request.readyState === 4){
                     if(request.status >= 200 && request.status < 300 || request.status === 304){
                         resolve(request.responseText)
                     }else{
                         reject('error')
                     }
                 }
             }
             request.send(data)
         })
     }
    
  12. this

     1. fn()
    
         this => window
     2. obj.fn()
         this => obj
     3. fn.call(x)
     4. fn.apply(x)
     5. fn.apply(x)
         this => x
     6. new Fn()
         this => 新的对象
    
     7. fn = ()=>{}
         this => 外面的this
    
    
  13. 闭包/立即执行函数

    声名一个匿名函数,然后立即执行它。在Es6之前,只能通过它来[创建局部作用域]。
    闭包:

     const add2 = function(){
         var count
         return function add(){
             count +1 = 1 //访问了外部变量的函数
         }
     }()
    

    闭包优点:

    1. 避免污染全局环境。
    2. 提供对局部变量的间接访问。
    3. 维持变量,使其不被垃圾回收。
  14. jsonp/cors/跨域

    jsonp,动态创建script标签,src指向请求地址,把callback函数名当做参数传给服务器,服务器把数据包装在callback内,传回来,然后script执行callback.

    cors:跨域资源共享

    1. 对于简单请求,乙站点在响应头添加Access-Control-Allow-Origin:http://甲站点
    2. 对于复杂请求,如POST,乙站点需要:
      1. 响应OPTIONS请求,响应中添加如下的响应头
        Access-Control-Allow-Origin:http://甲站点
        Access-Control-Allow-Mthods:POST,GET,OPTIONS
        Access-Control-Allow-Headers:Contet-type
        
      2. 响应POST请求,在响应中添加Access-Control-Allow-Origin头
    3. 如果需要附带Cookie,JS中需要在AJAX里设置xhr.withCredentials = true
  1. async await 捕获异常

     async function fn(){
         try{
             let a = await Promise.reject('error')
         }catch(error){
             console.log(error)
         }
     }
    
  2. 深拷贝

    1. 递归
    2. 判断类型
    3. 检测循环引用(环)
    4. 不可能拷贝 proto

      const cache = new Map()//缓存已拷贝部分
      function clone(object){
       if(cache.get(object)){//假如已缓存,直接返回
           return cache.get(object)
       }
       let result
       if(! (object instanceof Object) ){//基础类型直接返回
           return object
       }else if(object instanceof Array){
           result = []
       }else if(object instanceof Function){
          result = function(){return object.apply(this,arguments)}
       }else if(object instanceof Date){
           result = new Date(object-0)
       }
       else if(object instanceof RegExp){
           result = new RegExp(a)
       }else{
           result = {}
       }
       cache.set(object,result)//插入缓存
       for(let key in object){
           if(object.hasOwnProperty(key)){//非继承属性
               result[key] = clone(object[key])
           }
       }
       return result
      }
      
  3. 正则实现trim

    function trim(string){
        return string.replace(/^\s+|\s+$/g,'')
    }
    
  4. 继承

    es5

    function Animal(name){
        this.name = name
    }
    
    Animal.prototype.move = function(){
        console.log('move')
    }
    
    function Dog(){
        Animal.apply(this,arguments)
        this.foot = 4
    }
    
    let f = function(){}
    f.prototype = Animal.prototype;
    Dog.prototype = new f()
    
    Dog.prototype.constructor = Dog
    
    Dog.prototype.say = function(){
        console.log('汪汪汪')
    }
    
    let a = new Dog('aaa') //{name:'aaa',foot:4}
    a.name
    a.move()
    a.foot
    a.say()
    

    es6

    class Animal{
        constructor(name){
            this.name = name
        }
        move(){
            console.log('move')
        }
    }
    
    class Dog extends Animal {
        constructor(name){
            super(name)
            this.foot = 4
        }
        say(){
            console.log('汪汪汪')
        }
    }
    

    JS的new做了什么

    1. 创建临时对象/新对象
    2. 绑定原型
    3. 指定this = 临时对象
    4. 执行构造函数
    5. 返回临时对象
  5. 去重

    1. hash(计数排序的思路)

       var uniq = function(a){
           var map = {}
           for(let i =0;i<a.length;i++){
               let number = a[i]
               if(number === undefined){continue}
               if(number in map){//已重复
                   continue
               }
               map[number] = true //map里第一次出现
           }
           const result = []
           for(let key in map){
               result.push(key)
           }
           return result
       }
      

      缺点:数字只能是字符串,同时有数字跟字符串无法分出(’1’,1)

    2. set

       Array.form(new Set(a))
      
    3. Weekmap
       var uniq = function(a){
           var map = new Map()
           for(let i =0;i<a.length;i++){
               let number = a[i]
               if(number === undefined){continue}
               if(map.has(number)){//已重复
                   continue
               }
             map.set(number,true) //map里第一次出现
           }
          return [...map.keys()]
       }
      
      缺点:兼容性差了一些
  6. 手写Promise

    class Promises2 {
        #status = 'pending'
        constructor(fn) {
            this.q = []//创建一个队列
            const resolve = (data) => {
                this.#status = 'fulfilled'
                const f1f2 = this.q.shift()//出列,返回第一个
                const x = f1f2[0].call(undefined, data)
                if (x instanceof Promise2) {
                    x.then(data => {
                        resolve(data)
                    }, (reason) => {
                        reject(reason)
                    })
                } else {
                    resolve(x)
                }
            };
            const reject = (reason) => {
                this.#status = 'rejected'
                const f1f2 = this.q.shift()
                const x = f1f2[1].call(undefined, data)
                if (x instanceof Promise2) {
                    x.then(data => {
                        resolve(data)
                    }, (reason) => {
                        reject(reason)
                    })
                } else {
                    resolve(x)
                }
            }
            fn.call(undefined, resolve, reject)
        }
        then(f1, f2) {
            this.q.push([f1, f2])//入列
        }
    }
    
  7. 手写Promise.all

    1. 知道Promise上写而不是在原型上写
    2. 知道all的参数(Promise数组)和返回值(新Promise对象)
    3. 知道用数组来记录结果
    4. 知道只要一个reject就整体reject
    Promise.myAll = function (list) {
        const results = []
        let count = 0
        return new Promise((resolve,reject) => {
            list.map((promise,index) => {
                promise.then((r) => {
                    results[index] = r
                    count += 1
                    if (count === list.length) {
                        resolve(results)
                    }
                },
                    (reason) => {
                        reject(reason)
                    }
                )
            })
        })
    }
    
  8. JS垃圾回收机制

    1. 什么是垃圾
      1. 没有引用的就是垃圾
      2. 如果是对象互相引用,形成环也是垃圾
    2. 如何捡垃圾
      遍历和计数,如有引用则进行标记,最后把没有标记的删除
    3. 前端又有其特殊性(JS进程和DOM进程)

DOM

  1. 事件委托
    好处:

    1. 节省监听器
    2. 动态监听
      坏处:
    3. 调试比较复杂,不容易发现监听者。

      ul.addEventListener('click', function(e){
       if(e.target.tagName.toLowerCase() === 'li'){
           fn() // 执行某个函数
       }
      })
      
  1. mouse事件写一个可拖动的div
    1. 记录鼠标按下的坐标
    2. 记录当前拖动坐标
    3. 移动距离=拖动坐标-拖动坐标
    4. 元素的style.left/top+移动距离
        var position = null
        var drag = false
        xxx.addEventListener('mousedown',function(e){
                drag = true;
                position = [e.clientX,e.clientY]
        })
        document.addEventListener('mousemove',function(e){
            if(!drag) return //没有移动就别拖
                let X = e.clientX
                let Y = e.clientY
                let left = parseInt(xxx.style.left || 0 )
                let top = parseInt(xxx.style.top || 0 )
                moveX = X - position[0]
                moveY = Y - position[1]
                xxx.style.left = left + moveX + 'px'
                xxx.style.top = top + moveY + 'px'
                position = [X,Y]
        })
        document.addEventListener('mouseup',function(e){
            drag = false
        })
      

HTTP

  1. HTTP状态码

    HTTP status cat

  2. HTTP缓存有哪几种
    http1.1:

    Cache-control(强缓存): max-age 多少秒内过期 是相对时间 无请求 在本地
    Etag(协商缓存):MD5 在服务器 有请求 304
    http1.0:服务器最后修改时间,只能存到秒 有请求 304
    Expire(强缓存):日期 什么时候过期 Bug:本地时间用户可以调 无请求 在本地
    Last-Modified(协商缓存):

  3. GET 和 POST

    错:(背)

    1. POST安全 GET不安全
    2. GET URL有长度限制 POST没有
    3. GET 参数放在URL POST 放在消息体
    4. GET 只需要一个报文 POST 需要两个以上
    5. GET 幂等(不改变数据) POST 不幂等(改变数据库)
    6. GET结果会被缓存,POST结果不会被缓存
      对: 只语义上的区别 get 获取数据 post 提交数据
  4. Cookie Session Localstrage Sessionstrage 区别

    1. Cookie与Localstrage,cookie会被发送到服务器,4k,Localstrage不带请求,在本地,5M
    2. Localstrage与Sessionstrage,前者不会过期,后者会话结束后过期
    3. Cookie与Session,cookie存在浏览器,Session存在服务器,Session基于Cooike实现,具体做法就是把SessionId存在Cookie里
  5. HTTP2 HTTP1区别

    1. HTTP/2使用了二进制传输,而且将head和body分成帧来传输;HTTP/1.1是字符串传输。
    2. HTTP/2使用多路复用,HTTP/1.1不支持。多路复用简单来说就是一个TCP连接从单车道(不是单行道)变成了几百个双向通行的车道。
    3. HTTP/2可以压缩header,但是HTTP/1.1不行。
    4. HTTP/2支持服务器推送,但是HTTP/1.1不行。
  6. HTTP和HTTPS区别

    1. HTTP是明文传输的,不安全;HTTPS是加密传输的,非常安全。
    2. HTTP使用80端口,HTTPS使用443端口。
    3. HTTP较快,HTTPS较慢。
    4. HTPS的证书一般需要购买,HTTP不需要证书。
  7. TCP三次握手和四次挥手
    建立TCP连接时sever和client会经历三次握手

    1. 浏览器向服务器发送TCP数据,SYN(X)//请求数据
    2. 服务器向浏览器发送TCP数据,ACK(X+1),SYN(y)//表示同意
    3. 浏览器向服务器发送TCP数据,ACK(y)//表示同意

    关闭TCP连接时sever和client会经历四次挥手

    1. 浏览器向服务器发送TCP数据,FIN(X)//表示已完成
    2. 服务器向浏览器发送TCP数据,ACK(X+1)/表示同意
    3. 服务器向浏览器发送TCP数据,FIN(y)/表示已完成
    4. 浏览器向服务器发送TCP数据,ACK(y)//表示同意

      为什么2,3步骤不合并?因为2,3中间服务器很可能还有数据要发送,不能提前发送FIN

Vue

  1. watch computed 区别

    watch是属性监听无缓存
    computed是计算属性,有缓存

  2. 生命周期

    created:初始化
    mouted:数据请求
    updated:更新时做
    destory:销毁时

  3. 组件通信

    1. 父子 props $emit(‘事件’,data) $on(‘事件’,function(){})
    2. eventBus eventBus = new Vue();eventBus.$emit() eventBus.$on
    3. Vuex
  4. Vuex

    状态管理工具

    state
    getter
    mutatiion
    action

    …map

  5. vue2如何实现双向绑定的?

    1. v-model是v-bind:value和v-on:input的语法糖
      a: v-bind:value实现了data=>ui的单向绑定
      b: v-on:input实现了ui=>data的单向绑定
    2. 如何实现
      a: Object.defineProperty 给data创建getter/setter,用于监听data的改变,data一变就会安排改变ui
      b:后者通过template compiler给DOM添加事件监听,DOM input的值改变了就会去修改data
  6. vue.set

    vm.$set(‘目标对象’,key,value)

  7. vue-router

vue的官方管理器

重定向
histroy模式
懒加载 improt(‘./文件路径’)

  1. 路由守卫
router.beforeEach((to, from, next) => {
  // ...
})

next() //去to
next(false) //去from
next('/login') //去login 

组件内
 beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },

全局
router.beforeResolve
  1. 拦截

  2. 混用
    `bash
    //登录成功后将token存到seesionStorage

seesionstorage.setItem(‘token’,data.token)

//路由守卫
router.beforeEach((to,from,next)=>{
if(to.patch === ‘/login’) return next()
if(!sessionStorage.getItem(‘token’)) return next(‘/login’)
next()
})

//请求拦截
axios.interceptors.request.use(function(config){
config.headers.Authorization = seesionStorage.getItem(‘token’)
return config
})

//响应拦截
axios.interceptors.response.ues(function(response){
if(response.data.meta.status === 401){
location.href = ‘#/login’
}else{
return response
}
})


### vue3
1. vue3为什么使用proxy?
 1. 弥补Object.defineProperty的两个不足
    a:动态创建的data属性需要Vue.set来赋值,vue3用了proxy就不需要了。
    b:基于性能考虑,vue2篡改数组的7个API(push等),vue3用了proxy就不需要了。
 2. defineProperty需要提前递归遍历data做到响应式,而proxy可以在真正用到深层数据的时候再做响应式(惰性)

2. vue3为什么使用composition API?
   1. composition api比mixins、高阶组件、extends、Renderless Components等更好,原因有三:
    a:模板中的数据来源不清晰。
    b:命名空间冲突。
    c:性能

    2. 更适合TypeScript

3. vue3对比vue2做了哪些改动?
   1. createApp()代替了new Vue()
   2. v-model代替了以前的v-model和sync
   3. 根元素可以不止一个元素了
   4. 新增teleport传送门
   5. destory被改名为unmounted了
   6. ref属性支持函数了

### Webpack

1. 用过什么loader plugin
    1. loader 转换器
        1. babel-loader 把 JS/TS 变成 JS
        2. ts-loader 把 TS 变成 JS,并提示类型错误
        3. markdown-loader 把 markdown 变成 html
        4. html-loader 把 html 变成 JS 字符串
        5. sass-loader 把 SASS/SCSS 变成 CSS
        6. css-loader 把 CSS 变成 JS 字符串
        7. style-loader 把 JS 字符串变成 style 标签
        8. postcss-loader 把 CSS 变成更优化的 CSS
        9. vue-loader 把单文件组件(SFC)变成 JS 模块
        10. thread-loader 用于多进程打包

    2. plugin 扩展器
         1. html-webpack-plugin 用于创建 HTML 页面并自动引入 JS 和 CSS
         2. clean-webpack-plugin 用于清理之前打包的残余文件
         3. mini-css-extract-plugin 用于将 JS 中的 CSS 抽离成单独的 CSS 文件
         4. SplitChunksPlugin 用于代码分包(Code Split)
         5. DllPlugin + DllReferencePlugin 用于避免大依赖被频繁重新打包,大幅降低打
         包时间
         6. eslint-webpack-plugin 用于检查代码中的错误
         7. DefinePlugin 用于在 webpack config 里添加全局变量
         8. copy-webpack-plugin 用于拷贝静态文件到 dist

    二者的区别
    3. loader 是文件加载器(这句废话很重要)
        功能:能够对文件进行编译、优化、混淆(压缩)等,比如 babel-loader /
    4. plugin 是 webpack 插件(这句废话也很重要)
        功能:能实现更多功能,比如定义全局变量、Code Split、加速编译等
        运行时机:在整个打包过程(以及前后)都能运行

2. webpack 如何解决开发时的跨域问题?
    在开发时,我们的页面在 localhost:8080 ,JS 直接访问后端接口(如
    https://xiedaimala.com 或 http://localhost:3000 )会报跨域错误。
    为了解决这个问题,可以在 webpack.config.js 中添加如下配置:
    ```bash
    module.exports = {
    //...
    devServer: {
        proxy: {
        '/api': {
                target: 'http://xiedaimala.com',
                changeOrigin: true,
                },
            },
        },
    };
此时,在 JS 中请求 /api/users 就会自动被代理到
http://xiedaimala.com/api/users 。
如果希望请求中的 Origin 从 8080 修改为 xiedaimala.com,可以添加 changeOrigin:
true 。
如果要访问的是 HTTPS API,那么就需要配置 HTTPS 证书,否则会报错。
不过,如果在 target 下面添加 secure: false ,就可以不配置证书且忽略 HTTPS 报
错。
总之,记住常用选项就行了。
  1. 如何实现 tree-shaking?
    是什么
    tree-shaking 就是让没有用到的 JS 代码不打包,以减小包的体积。
    怎么做
    背下文档说的这几点:

    1. 怎么删
      a. 使用 ES Modules 语法(即 ES6 的 import 和 export 关键字)
      b. CommonJS 语法无法 tree-shaking(即 require 和 exports 语法)
      c. 引入的时候只引用需要的模块
         i. 要写 import {cloneDeep} from 'lodash-es' 因为方便 tree-shaking
         ii. 不要写 import _ from 'lodash' 因为会导致无法 tree-shaking 无用模块
      
    2. 怎么不删:在 package.json 中配置 sideEffects,防止某些文件被删掉
      a. 比如我 import 了 x.js,而 x.js 只是添加了 window.x 属性,那么 x.js 就要放到
      sideEffects 里
      b. 比如所有被 import 的 CSS 都要放在 sideEffects 里
    3. 怎么开启:在 webpack config 中将 mode 设置为 production(开发环境没必要tree-shaking)
      a. mode: production 给 webpack 加了非常多优化
  2. 如何提高 webpack 构建速度?

    1. 使用 DllPlugin 将不常变化的代码提前打包,并复用,如 vue、react
    2. 使用 thread-loader 或 HappyPack(过时)进行多线程打包
    3. 处于开发环境时,在 webpack config 中将 cache 设为 true,也可用 cacheloader(过时)
    4. 处于生产环境时,关闭不必要的环节,比如可以关闭 source map
    5. 网传的 HardSourceWebpackPlugin 已经一年多没更新了,谨慎使用
  3. webpack 与 vite 的区别是什么?

    1. 开发环境区别
      a. vite 自己实现 server,不对代码打包,充分利用浏览器对