小菜鸟的进阶之旅

468 阅读22分钟

编程题目:

1、数组扁平化:
将一个嵌套多层的数组转换为只有一层的数组 
// 1、递归的实现;如果每一层还是数组,就继续往下遍历
var arr = [1, 2, 3, [4, 5, [6]]]
function flattern(arr){
  let result = []
  arr.forEach(item=>{
    if(Array.isArray){
      result = result.cconcat(flattern(item))
    } else {
      result.push(item)
    }
  })
  return result
}
console.log(flattern(arr))

// 2、利用reduce函数
function flattern1(arr){
  return arr.reduce((res, next) => {
    return res.concar(Array.isArray(next) ? flattern1(res) : next)
  }, [])
}
console.log(flattern1(arr))

// 3、扩展运算符
function flattern2(arr){
  while(arr.some(item=> Array.isArray(item))){
    arr = [].concat(...arr)
  }
}

//4、split 和 tostring
function flattern3(arr){
  return arr.toString().split(',')
}

// 5、es6的flat函数
//  depth是flat的参数,depth是可以传递数组的展开深度,传入infinity代表不论传入多少层都要展开
function flattern4(arr){
  return arr.flat(Infinity)
}

// 6、json和正则共同实现
function flattern5(arr){
  let str = JSON.toString(arr)
  str = str.replace(/(\[|\])/g, '')
  str = '[' + str + ']'
  return JSON.parse(str)
}
2、数组转树形结构:
function translateListDatatToTreeData(list, root){
  const arr = []
  list.forEach((item)=>{
    // 首次传入空字符串 如果list的pid为空 那就是父节点
    if(item.pid == root){
      // 找到之后找item下面的子节点 以item。id为父id 往下找
      const children = translateListDatatToTreeData(list, item.id)
      if(children.length>0){
        item.children = children
      }
      arr.push(item)
    }
  })
  return arr
}

translateListDatatToTreeData(arr, '')

// 2、对象形式

function translate1(arr){
  
}

js:

css居中对齐的方式
1. 固定宽高:
    absolute+负margin(宽高的一半)
    absolute+margin auto (left: 02. 不固定宽高:
    flex
    absolute+translate
深浅拷贝
浅拷贝: 第一层是引用:引用指针;值:拷贝值
1、直接赋值
2、展开运算符 {...}
3Object.assign() 对象的合并方法
    将几个对象合并到一起  第一个参数是目标对象 后面的参数是源对象

   注意: 如果有重名的属性时 将会被后面的覆盖
         只有一个参数 直接返回该参数
         不是对象 会先转成对象  
         当参数是undefined 或是 null 会报错 不在首参报错
4、jquery的$.extend(deep, target, object1, object2)方法
5、数组浅拷贝:array的方法concat和slice

深拷贝: 拷贝栈和堆,重新开辟一块内存
1JSON.parse(JSON.stringify(obj))
2、jquery.extend() 
3、手写递归
    

function clone(target, map = new Map()){
    if (typeof target === 'object') { // 引用类型才继续深拷贝
        let obj = Array.isArray(target) ? [] : {} // 考虑数组
        //防止循环引用
        if (map.get(target)) {
            return map.get(target) // 有拷贝记录就直接返回
        }
        map.set(target,obj) // 没有就存储拷贝记录
        for (let key in target) {
            obj[key] = clone(target[key]) // 递归
        }
        return obj
    } else {
        return target
    }
}  
回流和重绘
前提:浏览器的渲染机制是流式布局
浏览器会将html解析成dom,将css解析成cssom。这两个产生render tree,浏览器计算节点的位置,将节点渲染到页面。
1、什么是回流:
当render tree 中的元素结构或尺寸变化导致整个文档重新渲染的过程
2、什么是重绘:
当render tree 中的元素的样式发生变化,比如颜色跟显示隐藏,而不是改变他在文档流中的位置的时候发生

重绘: 当页面元素样式改变不影响元素在文档流中的位置时,如background-color、border-color、visibility等,浏览器只会将新的样式赋予元素并进行重新绘制操作。

回流:当渲染树(render tree)中的一部分或全部因为元素的尺寸、布局、隐藏等改变时,浏览器重新渲染部分DOM或者全部DOM的过程

ps:回流必将引起重绘,而重绘不一定会引起回流
影响:回流造成的性能消耗大于重绘

如何减少回流和重绘: 1、使用css的简写 2、创建批量元素的时候,使用document.fragment() 3、减少table布局的使用 4、css尽量使用表达式

import 和 require 的区别
1import 在代码编译时被加载所以防在文件开头 require代码运行时加载
2、引入对象被修改时,import 的源对象会被修改 浅拷贝
3import对tree-shaking友好  移除js中未被引用的代码 
4import触发代码分割 放入不同的bundle中,按需加载
5import是es6的语法 药兼容浏览器的话必须改成es5的写法 requireAMD的引入规范

目前所有的引擎都没有实现import的引入方式,在webpack打包的时候都转为_webpack_require
块级元素和行内元素
                        特点           元素
块级元素:宽度100%     垂直排列  可以容纳其它块级元素或者内联元素  高 行高 内边距都可以控制 
    block:div ul-li form表单 table h1-h6 hr 水平分割线 p 段落 dl-dt-dd 定义列表 address 地址 
内联元素:宽度内容撑开  水平排列  只能容纳内联元素或者文本
    宽高无效 可以设置line-height 内外边距无效
     a 锚点 span select 选择 strong 粗体强调 img 图片input 输入框 label 表格标签 textarea 多文本输入 br 换行   
常见选择器
1、标签选择器  标签名{ 属性1: 属性值; }
2、类选择器    .类名 { 属性1.属性值1; }
3、id选择器   #id名 { 属性1: 属性值1; }  不能重复使用
4、通配符选择器   * { 属性名: 属性值 }
 css的复合选择器
1、后代选择器/包含选择器  元素1 元素2 { 样式声明 }
2、子选择器   元素1>元素2 {}
3、并集选择器  标签1,标签2 {}
4、伪类选择器  
5、链接伪泪选择器
    a:link          未被访问的链接
    a:visited       已经被访问过的链接
    a:hover         鼠标指向的链接
    a:actived       鼠标按下未弹起的链接
6、:focus伪类选择器
    input:focus {}     
px em rem 的区别
px 固定长度单位
响应式布局
em 相对长度 相对于父元素 来设置字体大小的 需要知道他父元素的大小
rem 相对于根元素
水平垂直居中的方法
1flex布局 
    justify-content:center; align-items:center;
2table布局
    display:table-cell; display: inline-block;
3grid网格布局
    
4、定位 + margin 负值 
    两个方向 margin-left: 宽的一半 margin-top:一半
    left: 50% top:50%
5、定位 + transform 负值 
    两个方向 left: 50% top:50% transform: translate(-50%, -50%)
6、定位 + margin: auto 四个方向0
盒模型 flex布局 浮动塌陷
margin border padding content四个部分 W3C和IE盒子
1、标准盒模型 
    元素的宽度=content宽度
2、怪异盒模型
    元素的宽度=content+padding+border
    
flexible box 弹性盒布局
    注:floatclearvertical-align失效
    属性: 排列方式:flex-direction: row column row-reverse column-reverse
          换行与否:flex-wrap: nowrap wrap wrap-reverse;
          换行和排列简写: flex-flow: direction wrap; 默认row nowrap;
          主轴对齐方式:justify-content: flex-start center flex-end 
              space-between 两端对齐 间隔相等 space-around 有边框距离 间隔相等;
          交叉轴排列:align-items: flex-start flex-end center 
              baseline 第一行文字的基线对齐 stretch 占满容器高度
          多根轴线的对齐:align-content: flex-start center flex-end space-between  
          space-around stretch
          
    项目的属性:
        order: 排列顺序 数值越小越靠前 默认0
        flex-grow: 放大比例 存在剩余空间不放大 项目占比
        flex-shrink: 缩小比例 默认1 
        flex-basis: 项目占据的主轴空间 设置为宽高值
        flex: grow shrink basis 的简写 默认 0 1 auto  auto(1 2 auto) none(0 0 none)
        align-self: 单个项目跟其他不同的对齐方式 可以覆盖align-items属性 
            auto flex-start flex-end center baseline stretch
 
浮动塌陷: 高度塌陷
    1、原因:父元素的高度不固定,默认子元素撑开,元素脱离文档流 无法撑开父元素的高度,导致福元素高度丢失,布局发生混乱
    2、解决方案:
        1、固定父元素高度
        2、块格式化上下文 触发bfc 开启bfc后 元素会变成一个独立的布局区域 不回影响外面的元素
        3、在父元素的内部最后添加一个空白的div,可以撑开父元素的高度,对其清除浮动 clear:both
        4、after伪类,选中box1后边的一个空白元素,清楚浮动 不在页面上添加多余的元素
            .name::after {
                content: '';
                display:block;
                clear:both;
            }
bfc特征:
    1、开启bfc的元素不会被浮动元素覆盖
    2、开启bfc的元素可以包含浮动元素
    3、福元素的垂直外边距不会和子元素重叠
如何开启bfc
    1、浮动 父宽度丢失 下边的元素上移
    2、元素设置为inline-block 宽度丢失
    3、overflw设置为visible
    4、设置绝对定位
    5overflow:hidden  副作用最小的方式
css3新特性
css1: 网页对象的基本样式 字体 颜色 背景 边框 
css2: 添加高级概念:浮动 定位 高级选择器(子选择器 相邻选择器 通用选择器)
支持圆角 多背景 透明度 阴影 动画 图表 
前端布局
1、静态布局 px为单位 固定宽度 不会随着pc端的屏幕大小变化
2、弹性布局 flexible   简便 完整 响应的实现页面的布局 使用em 或者rem 相对布局 百分比更灵活方便 
3、自适应布局 媒体查询 @media 给不同的尺寸的设备切换不同的样式 
4、流式布局 按照屏幕的分辨率适配调整页面 整体布局不变  使用%定义宽度 高度px 根据可视区域和福元素的尺寸调整 配合min-width/max-width控制尺寸流动范围
    缺点:屏幕太大或太小导致元素无法正常显示
5、响应式布局 一个网站能够兼容多个终端 
    媒体查询+流式布局 适应pc端和移动端
6、浮动布局    脱离文档流 但是不脱离文本流  float:left; float:right;
    兼容性好 但是页面宽度不够的时候影响布局
7、定位布局 position控制页面元素 设置一些不规则布局
HTML5 新特性
1、语义化标签  网页结构更加清晰 有利于seo
    1header头部区域 footer地步区域 nav导航链接的部分section文档的节 段 aside artical 页面独立的内容区域
2、视频音频 video audio 无需引入第三方插件
3、画布 canvas 可绘制2D的图形和动画
4、更加智能的表单
5、svg绘图
6、拖放api   
7、地理定位
8、webworker
9、webstorage
10、websocket
前端优化
1、缓存优化
2、请求优化
3、引入外部资源是不要出现超时 404状况
4、合理设置cookie的大小以及过期时间
5、懒加载预加载使用
浏览器兼容
常见的浏览器兼容问题:
1、不同浏览器的标签默认的补丁和内补丁不同
    css添加通配符 *{margin:0;padding:0;}
2、IE6双边距:IE6设置了 floatmargin 显示双边距
    display:inline;
3、标签的高度设置为小于十的数值 IE6、7会显示超出自己的高度
    display:inline;
4、图片默认又间距
    使用floatimg布局
5、IE9以下不能使用opacity
    opacity: 0.5; filter:alfha(opacity=50);filter:progid;
    解决方案:opacity0.5filter:alfha(opacity=50);filter:progid:DXlmageTransform.Microsoft.Alfha(style=0,opacity=50);
6、边距重叠 当相邻元素都设置了marginmargin取最大值
    1 给父元素添加overflow:hidden;子元素的高度加上外边距高度小于父元素的高度 否则子元素的高度就会被隐藏掉
    2 给父元素加边框 透明border
    3 给父级或子级添加 display:inlineblock;
    4 设置float
    5 position:absolute
    6、给父元素添加padding
7cursor:hand;手势在Safari上不支持
    cursor:pointer;
8、块级元素
   

8.31 勤实

1、element UI的表单校验 动态表头
1、表单校验:
    el-form 加上rules字段开启表单验证规则,rules在script里面定义并且绑定动态对象,对象里面包含的是要验证的字段。
    items与props属性对应
    @click绑定事件,给el-form绑定ref属性作为元素唯一的标识,通过this.$refs.loginform.validate() 处理校验结果。
2、动态表头
v-for进行简化,formatter列格式化
2、webstorm的两种存储方式
http缓存 

1、强缓存:设置:http请求头中的expires和cache-control
  不会向服务器发送请求,直接从缓存中读取资源、请求返回200的状态码,from momory cache 内存, from disk cache(硬盘读取),顺序是momory-》disk,js和图片解析后存入内存,读取,css在硬盘

2、协商缓存:设置:http请求头中的Etag和Last-modifed
  是在强缓存失败后,浏览器携带缓存标识再次请求服务求加载资源
生效返回304not modified

协商缓存两种方式的对比

首先在精确度上,Etag要优于Last-Modified,Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。

性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值

appcache优先于强缓存,强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。

2、本地存储
cookie:
localstorage:
sessionstorage:

一、容量 
cookie容量在4K左右,且有条数限制。localStorage的容量有5M。
二、是否向服务器发送数据
cookie会向服务器发送数据,localStorage不会往服务器发送数据。
三、过期时间 
cookie的有过期时间,在没有设置过期时间,关闭浏览器就消失,默认过期时间是一次会话。localStorage没有过期时间。
四、路径限制 
cookie有路径的限制。localStorage没有路径的限制。
五、存储类型 
cookie存储的是字符串,字符串,字符串。localStorage存储的是对象,对象,对象。
3、css引入的方式以及优先级

行内 > 内部嵌入 > 外部链接

4、vuex的原理,比较大的项目的话如何取vuex里面的数据
1、vuex是什么
    vuejs的状态管理工具,是集中的数据管理仓库
    
    原理:在每一个组件的beforeCreate()方法注入了this.$store这样的一个对象。在任意的组件中都能找到store对象。
    
    组成:
    state: 存储基本数据
    mutations: 提交更改数据
    actions: 处理异步。使用this.$store.commit方法对mutations里的方法进行触发从而修改state的值
    getters: 相当于vue的computed属性
    modules: 将store分割为多个模块,都有各自的state,actions,modules,getters
2、为什么用vuex
    存取公共的数据
3、怎么用
    调用diapatch方法触发actions相关的处理,使用commit方法提交mutation修改state。通过getters获取到state的新值。提供mapstate,mapgetters,mapactions,mapmutations等辅助函数在开发中处理store,重新渲染vue components,页面随之更新。
4、优点缺点
5、vuex的模块化,如何取模块里的值
    获取数据 this.$store.state.模块.数据字段
    vuex中的数据在刷新时丢失原因,如何解决?
    原因:vuex的数据只是存在页面中,相当于全局变量,刷新的时候vuex会初始化,,存在运行内存里的,会重新加载实例,重新赋值
    解决:
    1、第三方库:vuex-persistedstate
        默认localstorage中,
        设置sessionstorage
        插件的

    2、localstorage
    
    
    我们经常遇到一个问题就是,刷新页面导致状态丢失,一个解决方案就是使用 sessionStorage 随时储存 state,刷新页面出发 created 则判断 sessionStorage.state 是否有内容,有则覆盖原 state

1.  replaceState 是覆盖 state ,合并的工作要使用 Object.assign() ,当然了,大部分时候并不需要合并,因为 sessionStorage 里的就是最新的 state ,直接覆盖就行了
1.  尽量避免使用这个方法,在错误的位置使用这个方法会造成数据被错误覆盖,只应该在非常有必要恢复 state 的时候才使用,更多的时候,如果用户刷新页面,应让用户从头走操作流程,只有在连续答题、购物等少数场合需要用到,而且并不是必须使用,依然有其他变通方法
    
6、http的加密算法,https的传输过程中的加密,数据的加密
7、v-show和v-if的区别
v-if通过控制dom元素的删除和生成来显示隐藏,每一次都会重新跑一遍生命周期
v-show控制dom元素的css样式,不回销毁
频繁或者大数量的使用v-show
8、vue的路由跳转方式:
前端路由要做的两件事:
1、保存当前页面状态
2、使用浏览器的前进后退功能

开发者:
1、改变url但是不发请求
2、解析url
hash 模式
window.location.hash() onhashchange()方法获取hash1.  location.hash 的值实际就是 URL 中'#'后面的东西 它的特点在于:hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
2.  可以为 hash 的改变添加监听事件
history模式
利用html5中的pushState和replaceState方法,用于浏览器的记录
9、router的push和replace区别

把路由router想象成一个访问记录的栈,router.replace() 是替换掉栈顶,而router.push() 则是向栈中再堆入一个新记录。

授权请求的那页面应该用replace去替换掉自身的访问记录,防止用户跳到下一步流程后按后退键回退到授权页,而导致重复授权

10、nextTick作用

vue实现响应式不是数据更新之后dom立即变化,而是有一定的更新策略 nextTick的作用是在下次dom更新循环之后延迟执行回调,在数据修改之后使用,获取更新之后的dom

11、token过期之后还想请求另一个接口,清除个人中心的数据,修改个人中心的状态为未登录
token: 服务端api都会设置token来保障接口的识别安全以及认证,token有实效时间,过期后有两种解决方案
1、手动处理
    实效后主动重新获取token,直接跳转登陆页面,获取新的token,更新本地缓存
    判断token失效:配置请求拦截
2、自动处理
    马上获取一个新的token,保障接口正常请求完成
HTML
HTML基本结构
文档类型声明
html标签
head标签
body标签
元数据标签
常用的HTML元素
HTML文本
标题标签
段落标签
链接标签
图片标签
列表标签
表格标签
HTML表单
表单元素
表单属性
表单验证
HTML5新特性
语义化标签
视频和音频标签
canvas标签
地理位置标签
CSS基础
介绍CSS的概念和作用
学习CSS基础语法
了解CSS选择器和属性
学习CSS盒模型和布局
掌握CSS文本样式和字体
学习CSS背景样式
了解CSS浮动和定位
学习CSS动画和过渡效果
掌握CSS响应式设计
    为什么需要CSS响应式设计
    如何实现CSS响应式设计
    使用媒体查询
    使用弹性布局
    使用网格布局
    使用相对单位
    设计适配移动设备的布局
    设计适配平板设备的布局
    设计适配桌面设备的布局
    测试CSS响应式设计
    常见问题及解决方法
JavaScript概述
数据类型和变量
运算符
流程控制
函数
数组
对象
面向对象编程
错误处理
事件处理
DOM操作
Ajax技术
ES6新特性
模块化开发
Vue
Vue简介
Vue核心概念
数据绑定
组件化应用
生命周期
指令
Vue组件
组件的定义和使用
组件之间的通信
组件的生命周期
Vue路由
Vue状态管理
Vue模板语法及指令
Vue插件
Vue单元测试
Vue的优缺点
JQuery
介绍JQuery
JQuery的历史和背景
JQuery的特点和优势
JQuery的基础语法
JQuery的选择器
JQuery的DOM操作
JQuery的事件处理
JQuery的动画效果
JQuery的AJAX
JQuery UI
JQuery插件
JQuery的使用范例
JQuery的性能优化
JQuery与其他库的比较
移动端适配
移动端适配的基本原理
移动端适配的常用方法
使用rem进行移动端适配的具体步骤
使用vw/vh进行移动端适配的具体步骤
使用flexible.js进行移动端适配的具体步骤
使用postcss-px-to-viewport插件进行移动端适配的具体步骤
移动端适配中遇到的常见问题和解决方法
针对不同屏幕尺寸的适配需求的解决方案
移动端适配的优缺点分析
移动端响应式设计的概念和原理
使用响应式设计进行移动端适配的具体步骤
响应式设计中遇到的常见问题和解决方法
针对不同设备类型的适配需求的解决方案
移动端适配的未来发展趋势
HTTP协议
HTTP协议的定义及作用
HTTP协议的发展历程
HTTP报文的组成结构
HTTP请求方法:GET、POST、PUT、DELETE等
HTTP响应状态码:1xx、2xx、3xx、4xx、5xx等
HTTP请求头部信息:User-Agent、Cookie、Referer等
HTTP响应头部信息:Content-Type、Content-Length、Server等
HTTP的长连接与短连接
HTTP的缓存机制
HTTPS协议的概述
HTTP/2协议的特点与优势
HTTP/3协议的概述与优势
HTTP协议在移动端的应用
HTTP协议在Web安全中的应用
HTTP协议的未来发展方向
前端安全
常见前端安全问题
    跨站脚本攻击(XSS) 提交恶意代码 浏览器执行恶意代码
    存储型 反射型 dom型 
    1、输入过滤
    2、纯前端渲染 
    3、转义html textcontent() setAttribute()
    跨站请求伪造(CSRF)攻击者诱导受害者进入第三方网站 受害者向第三方网站发请求
     get post 链接
    1、同源检测:请求头中的origin和referer
    2、csrf token
    3、cookie双重验证
    sql注入
    
引起前端安全的问题
    1、跨站脚本攻击
    2、请求伪造
    3iframe滥用
    4、第三方库
    
    
    
劫持:
    1、dns:dns强制解析 302跳转
    2、http:修改请求的响应  方案:https



    

    
    
前端安全解决方案
    输入输出过滤
    Cookie 安全
    HTTPS
    前端框架的安全机制
    安全审计
跨域问题
什么是跨域问题
跨域问题的原因
常见的跨域场景
跨域问题的影响
跨域解决方案概述
JSONP
跨文档消息传递(postMessage)
修改document.domain
CORS(跨域资源共享)
使用代理服务器
隐藏iframe技术
WebSocket协议
前端工程化
什么是前端工程化
为什么需要前端工程化
前端工程化的好处
前端工程化的基本原则
前端工程化的工具和技术
构建工具
打包工具
自动化测试工具
代码规范工具
性能优化工具
可视化工具
前端工程化的应用场景
单页应用
多页应用
移动端应用
桌面端应用
小程序
前端工程化的未来发展
前端性能优化前端性能优化
为什么需要前端性能优化
如何衡量前端性能
优化前端代码
压缩代码
减少HTTP请求
使用CDN加速
使用缓存
优化前端资源加载
延迟加载
异步加载
预加载
优化前端渲染性能
减少DOM操作
使用CSS动画代替JS动画
使用虚拟DOM
前端职业规划
了解前端发展趋势
掌握前端基础知识
深入学习前端框架与库
学习前端工程化与自动化
掌握前端性能优化
了解前后端分离与服务端渲染
学习移动端开发
熟悉响应式布局与设计
掌握前端安全与防御
熟练使用代码版本控制工具
了解团队协作与项目管理
关注用户体验与可访问性
学习数据可视化与交互设计
关注新技术与新应用
前端面试技巧
准备面试前的必要知识点
面试前的准备工作
面试时的注意点
基础知识的考察
算法和数据结构的考察
常见前端框架的考察
HTML、CSS、JavaScript的考察
性能优化的考察
前端工程化的考察
面试过程中的表现技巧
面试后的总结与反思
面试成功的关键因素
面试失败的处理方法
如何在面试中脱颖而出
如何提高面试技巧的方法

8.31 宇信科技

1、从建立连接到网页呈现的过程

1、解析URL:用户在浏览器中输入url,浏览器对url进行解析;

2、缓存判断:浏览器先后在浏览器缓存、系统缓存和路由缓存中查找请求的资源,如果找到了,浏览器会拦截请求,直接结束请求,使用查找到的资源。这样做的好处是可以缓解服务器压力,提升性能(获取资源的时间更短了);如果找不到就将请求发送给DNS服务器;

3、DNS解析:发送到DNS(域名服务器)获得域名对应的Web服务器的IP地址。DNS服务器会先判断本地是否有该域名的IP地址缓存,没有则向本地DNS服务器发起请求,如果没有则像根域名服务器发起请求,获得负责顶级域名服务器的地址后,再向顶级域名服务器发送请求,获得负责权限域名服务器的地址后,再向权限域名服务器发起请求,最终获得域名的IP地址,最后本地DNS服务器将IP地址返回。用户向DNS服务器发起请求属于递归查询;本地DNS服务器向各级域名服务器发送请求属于迭代查询。

4、获取MAC地址:当浏览器得到IP地址后,传输数据还需要直到目的主机的MAC地址,因为数据链路层发送数据需要知道通信双方的MAC地址。

5、三次握手:获取到MAC地址后,客户端浏览器与WEB服务器建立TCP连接(三次握手);

6、SLL/TSL协议握手

7、发送HTTP请求

8、服务器处理HTTP请求,返回数据;当页面请求发送到服务器后,服务器会返回一个html文件作为响应,浏览器接收到响应后,开始对html文件进行解析,开始页面渲染过程。

9、页面渲染:浏览器根据HTML文件构建DOM树,根据CSS文件构建CSS树,当DOM树和CSS树构建好后,根据他们来构建渲染树,根据渲染树进行布局,布局完成后,使用浏览器接口对页面进行绘制,这时整个页面就显示出来

10、TCP四次挥手

2、回流和重绘
1、是什么
    浏览器的渲染机制:流式布局
    html->dom, css->cssom ===> render tree
2、为什么
    当render tree中的dom的结构发生变化的时候导致回流产生
3、怎么办
    减少使用table布局
    css的使用表达式
    css简写
    使用批量创建元素 document.fragment()
3、浏览器的存储方式区别
cookie:
localstorage:
sessionstorage:
存储大小
有效期
作用域范围
4、跨域的方式,配置的属性
1、为什么要跨域
    前提:
    js有同源策略出于安全方面的考虑:当前页面与请求页面的协议,域名,端口号全部相同时才可以请求资源。
    同源策略限制内容:
    1、cookie等存储性操作
    2、不允许dom操作
    3、ajax请求
    
2、什么是跨域
    不同域名之间的请求,js的同源策略的限制
    在这个限制下,客户端的请求可以发出去,服务端也可以处理请求,但是返回的资源被浏览器拦截。
    
3、怎么处理跨域
    注:协议和端口造成的跨域前台没法处理
    域名不同:url的首部识别
    域仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”。
    
    1、天然支持跨域:
    imgsrc属性
    script的src属性
    link的ref标签
    
    解决方法:
    1、jsonp:script的src属性,(缺陷:仅支持get方法)
    2、cors:浏览器端跟客户端都要支持
        在服务器端设置同源策略:响应头添加 access-control-allow-orioin属性,*代表所有
    3、websocket:html5的持久化协议,实现了浏览器与服务器之间的全双工通信,也是跨域的解决方案。但是在建立连接时需要通过http协议。
    首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。 

    解决了http不能实时更新的弊端,即时回话。
5、水平垂直居中的方式 属性
6、盒模型 区别
区别:内容区域
标准:设置的宽高==content  实际的宽高== content
怪异:设置的宽高==实际的宽高==content+内外边距+边框

flex布局:自适应的流式布局

7、深浅拷贝
8、防抖和节流
1、什么是防抖节流
    防抖:一段时间内只触发最后一次,防止事件的高频触发
    (比如页面的多次缩放,输入框的输入监听,用户输入完成之后再触发)
    节流:隔一段时间触发一次
2、怎么解决
    防抖:等用户操作完了再触发
        事件触发==>开启定时器==>如果再次触发,则清除上一次的定时器,再写一个定时器,定时时间到则触发
        function debounce(fn, delay){
	let timer = null;
	return function(){
		clearTimeout(timer);
		timer = setTimeout(()=> {
			fn.apply(this, arguments);
		}, delay)
	}
} 
    节流:上一个结果出来以后或者隔一段时间再触发
    防抖造成的问题:一直操作导致一直不触发,正确思路应该是点击一次就发送,等结果回来后再发送
    事件触发==>执行操作==>关闭阀门==>后续操作无效==>一定时间后阀门打开==>操作触发
    function throttle(fn, delay){
	let valid = true;
	return function(){
		if(valid) {
			setTimeout(()=> {
				fn.apply(this, arguments);
				valid = true;
			}, delay)
			valid = false;
		}
	}
}

总结:
    防抖节流都是为了防止事件高频触发导致浪费性能
9、数组常用的方法
1、新增删除
push() 数组末尾添加
pop() 数组末尾删除
unshift() 数组首位添加
shift() 数组首位删除
slice() 指定位置截取 ps:不改变原数组
splice() 数组增删改 
join() 拼接成字符串 ps:不改变原数组
concat() 连接多个数组 ps:不改变原数组
indexOf() 检测出现的索引 ps:不改变原数组
lastIndexOf() 最后一次出现的索引 ps:不改变原数组
includes() 是否包含一个指定的值 ps:不改变原数组
sort() 排序 
reverse() 倒叙排列数组元素
forEach() 遍历 ps:不改变原数组
10、闭包

闭包是指一个函数有权访问外部作用域中的变量,这个函数就是闭包,所有的js函数都是闭包。

优点:内部函数可以访问外部函数的变量
缺点:
- 外部函数被引用的变量会存在内存中不被销毁
- 不被垃圾回收而占用内存
- 导致性能降低

会导致内存泄漏造成网页性能问题,在推出函数时将不使用的变量全部删除
不要随便改变副函数内部的值

如何解决:

1. 使用立即执行函数
2. 使用es6的let
3. 使用settimkeout的第三个参数
11、原型和原型链 作用域和作用域链
原型:每一个对象都有一个prototype属性,是原型对象,他有一个construct属性,指向其构造函数,含有一个__proto__属性,指向原型对象,
原型链:当访问一个对象时,会在他自身找,然后在他原型上找,原型也有一个原型对象,这样依次往上找,这个过程就叫原型链,直到找到这个属性或者到达原型链的顶端null
终点:Object.prototype.__proto__ === null

作用域:
全局作用域:未定义直接赋值的变量 最外层函数和最外层函数外面定义的变量 所有window对象拥有全局作用域
函数作用域:声明在函数内部的变量
块级作用域:letconst 声明的变量

作用域链:
当查找一个变量的时候,在当前作用域中查找,没有的话去父级作用域查找,依次向上,直到访问到window对象就终止,这一层层的关系就是作用域链

12、es6的新特性
13、async、await使用
14、判断数据类型
15、白屏优化,webpack优化、打包优化
16、vue的生命周期
17、数据的双向绑定
18、组件的封装
19、组件之间传值方式
20、v-if和v-show
22、后台管理的一个模块的授权处理
置换元素
background-attachment:fixed;

9.1 风暴

1、基本数据类型和引用数据类型

基础: number, string, boolean, undefined, null,symbol, bigInt 复杂: object(function, array, date, regexp, math, set, map)

基本数据类型存储在 栈

复杂数据类型存储在 堆

如何判断数据类型: typeof

 typeof null == 'object' 
 typeof {} == 'object' 
 typeof [] == 'object' 
 typeof function () {} == 'function'

判断引用数据类型: 1、instanceof 判断是否出在该原型链的任何位置(判断一个变量是否属于某个对象的实例)

 consol.log(null instanceof Object) false
 consol.log({} instanceof Object) true

2、toString

console.log(toString.call(null)) // object
console.log(toString.call(undefined)) // undefined
console.log(toString.call({})) // object
console.log(toString.call([])) // array
console.log(toString.call(function(){})) // [object function]

其他转换: constructor: 判断是否是该类型直接继承者

堆栈的区别: 1、申请方式:栈自动分配,堆人为申请开辟 2、申请大小:栈空间较小,堆空间较大 3、申请效率:栈效率高,堆速度慢 4、存储内容不同:栈在函数调用时,函数调用语句的下一题哎可执行语句的地址第一个进站,然后函数的各个参数进站,静态变量不入栈。而堆事笑死又不用一个字节存放堆的大小,堆的具体内容是人为安排 5、底层不同:栈连续的空间,堆不连续的空间

2、内存泄漏

程序中已经分配的堆内存由于未被释放或无法释放造成系统的浪费导致系统运行速度变慢甚至崩溃等后果

原因以及解决方法
1. 使用静态内部类,避免线程造成的内存泄漏
2. 推出程序前,清空集合里的东西
3. 使用缓存的converView构造adapter,避免使用listview造成的内存泄漏
4. 定时器未清除
5. dom清空时还存在引用
3、垃圾回收机制
定义:为了防止内存泄漏,寻找这些不再使用的变量并且释放掉它所指向的内存
变量的生命周期:
当一个变量的生命周期结束后,它所指向的内存空间就会被释放。js有两种变量,局部变量和全局变量,局部在函数结束之后内存被释放,全局变量回等浏览器关闭才销毁。
js的垃圾回收机制:
1、标记清除
大部分浏览器都是用这种回收机制,当变量进入执行环境的时候,垃圾回收机制将该变量进行标记,当变量离开的时候再度标记随后清除
2、引用计数
会引起内存的泄漏,主要变量声明并且将一个引用类型值复制给该变量的时候引用书加一,当这个变量指向其他一个的时候引用数量减一,当为0事回收机制进行回收。
4、两个变量循环引用的时候如何清除

当对象1中的某个属性指向对象2,对象2中的某个属性指向对象1

5、为什么js是单线程 浏览器渲染进程中有哪些线程
假如说一个线程在操作某个dom,另一个线程在删除dom的话浏览器就不知道该怎么做了

1、gui渲染线程 图形用户界面
2、js
3、事件
4、定时器
5、异步http请求
6、https和http的区别
7、https的实现原理
8、vue的生命周期
vue中el和$el有什么区别?挂载的时候两者发生了什么?  
有看到说挂载的时候将$el的内容挂载到了el,相当于我们在jquery执行了$(el).html($el),生成页面上真正的dom。想知道它们的具体区别

里面提到的挂载是什么意思?
让Vue实例控制页面中的某个区域的过程,称之为挂载

el是Vue实例的挂载目标。在实例挂载之后,元素可以用 vm.$el 访问。挂载阶段还没开始的时候,$el属性是不可见的。Vue生命周期mounted阶段,el被新创建的vm.$el替换,这个时候Vue实例的挂载目标确定, DOM渲染完毕。在这个Vue实例当中,也就可以使用vm.$el访问到el了。具体参考Vue文档API
9、vue的优化方式
10、v-if和v-show
11、接触过的算法
1、排序算法
2、
12、 事件循环机制 同步跟异步 宏任务和微任务
js单线程 调用栈/执行栈 
任务队列:
    宏任务:定时器,i/o,js整体代码,ui Rendreing
异步队列
    宏任务:settimeout/setinterval/setimmidate,
    微任务: promise.then/catch/finally,async await, nextTick
优先级:nextTick>.then>settimeout>setimmidate
    注意:async是通过Promise包装异步任务 *await后面的代码,会进入then微任务中*
同步:阻塞式
    客户端在请求服务端的时候,会等待返回结果,不会做其他事
    new Promise 创建实例的过程是同步的
异步:非阻塞式
    一个请求发出不需要等到结果就可以执行下面的操作,提高执行效率
使用引用计数的问题

9.1 中恒

1、大屏的尺寸计算方式
2、重绘回流区别
3、什么操作可以减少上面两种情况的发生
4、盒模型
5、flex布局的属性以及使用场景
6、清除浮动的方式
为什么要清除浮动:
    浮动导致的问题:
     1、父元素的高度塌陷
     2、如果不是第一个浮动元素,会影响页面结果显示
如何清除:
    1clear:both
    2、伪元素:clearfix
    3overflow使用
    4、双伪元素
    5、撑起父元素的高度
7、数组的去重
1、双重for循环
2for+findindex
3、includes 新数组是否包含旧数组的每一项
4for+object 对象的属性名不能重复
8、深拷贝浅拷贝
浅:拷贝值
展开运算符
object.assign
concat slice
深:引用和值
9、深拷贝的方法
json.parse(json.stringify)
手写递归:递归便利对象,知道里面全是基本类型为止再复制
10、js判断数据类型的方式
typeof
instanceof
tostring
constructor
11、vue的date为什么是一个函数而不是一个对象
组件时可以复用的实例,一个组件创建好之后可能被用到各个地方,复用组件的时候组件的data应该是相互隔离互不影响的
如果data是对象的话,每当被复用是,复用的对象和源对象都会指向同一个内存地址(浅拷贝),互相之间相互影响,所以要是函数
12、vue的数据双向绑定原理
数据劫持结合发布订阅模式实现
监听器observer,监听所有属性,属性发生变化来了要告诉订阅者是否更新,指令解析器compile对每个节点进行扫描,

(1)实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

(2)实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

(3)实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。
13、vue如何监听数组变化
深度监听:
watch: {
    list:
        handler(oldval,newval){
            ...
        },
        deep: true
    }
}
14、可以改变数组长度的方法
push/pop
unshift/shift
splice 删除元素
15、vue的mvvm
vue实现数据双向绑定主要是:采**用数据劫持结合发布者-订阅者模式**的方式,通过**Object.defineProperty()**来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。

采用数据劫持结合发布订阅模式,使用object.defineproperty方法,来劫持各个属性的settergetter,在数据变动的时候将法系哦阿西给订阅者,触发相应的回调,将mvvm作为数据绑定的入口,整合observer,compile和watcher,通过observer来监听自己的model的数据变化,最终watcher作为桥,达到数据变化视图更
16、组件之间的传值
1.父组件传值给子组件,props
2.子组件传值给父组件,$emit+事件
3.组件中过使用$parent$children获取到付组件实例和子组件实例
4.$attrs$listeners,在对一些组件二次封装时传值
5.使用$refs获取组件实例
6.使用vuex进行状态管理
7.eventbus跨组件触发事件从而进行传递
8.使用provide和inject
9.使用本地浏览器进行缓存,localstorage
17、项目的登陆鉴权以及promise
鉴权:验证用户是否拥有访问系统的权利
方法:1、http basic authentication,seesion-cookie, OAuth
需求分析:
- 、登陆成功,后端返回token
- token带有时效性,过期无效
- 前端调用接口时必须携带token
- 前端在跳转需要权限的页面时,需要判断当前是否已经登陆,以及登陆是否过期
技术栈:
vue,node.js作为框架
axios作为请求接口的http库
express作为接口开发的框架
前端:
1. axios实现请求拦截,响应拦截
2. router实现特定页面鉴权跳转
3. vuex对认证状态进行管理
import axios from 'axios'
import store from '../store'

/**
 * Axios 基本配置封装(默认配置,可被覆盖)
 * @baseURL 基础路径(前缀)
 * @timeout 超时时间
 * @responseType 响应数据类型 (json)
 * @withCredentials 是否允许带cookie等
 * @header 根据不同请求设置
 */
const Axios = axios.create({
    baseURL: '/',
    timeout: 10000,
    responseType: 'json',
    withCredentials: true,
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
})

// 请求拦截,一旦调用接口,将vuex中的loading设置为true,显示加载页面
Axios.interceptors.request.use(config => {
    store.dispatch('setLoading', true)
    if (localStorage.Token) {
        // 当缓存中存在Token时,将Token设置为请求头的 Authorization
        config.headers.Authorization = localStorage.Token
    }
    return config
}, error => {
    // 请求报错时 loading 更新为 false
    store.dispatch('setLoading', false)
    return Promise.reject(error)
})

// 响应拦截,一旦接口返回,将vuex中的loading设置为false,显示加载页面
Axios.interceptors.response.use(response => {
    store.dispatch('setLoading', false)
    return response
}, error => {
    // 响应报错时 loading 更新为 false
    store.dispatch('setLoading', false)
    return Promise.reject(error)
})

export default Axios
/*
 * 存放 Api 接口文件,在页面中直接引入对于接口,即可使用
 * @userRegister 注册接口
 *      registerInfo 注册表单数据
 * @userLogin 登录接口
 *      loginInfo 登录表单数据
 * @getUserInfo 获取登录人信息 - 此接口需要进行鉴权认证,不通过是无法调用
 */
 
import Axios from './http.js'

export function userRegister(registerInfo) {
    return Axios({
        url: '/hdgc/users/register',
        data: registerInfo,
        method: 'post',
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        }
    })
}
export function userLogin(loginInfo) {
    return Axios({
        url: '/hdgc/users/login',
        data: loginInfo,
        method: 'post',
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        }
    })
}
export function getUserInfo(username) {
    return Axios({
        url: '/hdgc/users/',
        data: username,
        method: 'get'
    })
}

/*
 * 存放 Api 接口文件,在页面中直接引入对于接口,即可使用
 * @userRegister 注册接口
 *      registerInfo 注册表单数据
 * @userLogin 登录接口
 *      loginInfo 登录表单数据
 * @getUserInfo 获取登录人信息 - 此接口需要进行鉴权认证,不通过是无法调用
 */
 
import Axios from './http.js'

export function userRegister(registerInfo) {
    return Axios({
        url: '/hdgc/users/register',
        data: registerInfo,
        method: 'post',
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        }
    })
}
export function userLogin(loginInfo) {
    return Axios({
        url: '/hdgc/users/login',
        data: loginInfo,
        method: 'post',
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        }
    })
}
export function getUserInfo(username) {
    return Axios({
        url: '/hdgc/users/',
        data: username,
        method: 'get'
    })
}

beforeEach实现页面权限跳转

import Vue from 'vue'
import Router from 'vue-router'
import store from '../store';
import jwt_decode from 'jwt-decode'
import { Message } from 'element-ui'
Vue.use(Router)

// ...

route.beforeEach((to, from, next) => {
    // 若返回首页,无须鉴权
    if (to.path == '/') {
        next()
    } else {
        /**
         * 判断当前是否存在Token
         * @存在则进行鉴权判断
         * @不存在则返回首页
         */
        if (localStorage.Token) {
            /**
             * 判断当前Token是否过期
             * @过期则跳回首页
             * @未过期则成功跳转
             */
            const decoded = jwt_decode(localStorage.Token)
            const currentTime = Date.now() / 1000
            console.log('Token_Decode & currentTime', decoded, currentTime)
            if (decoded.exp < currentTime) {
                Vue.prototype.$notify({
                    title: 'Tips',
                    message: 'Token过期,重新登录',
                    type: 'error',
                    duration: 3000
                })
                store.dispatch('clearCurrentState') // 清空vuex
                next('/')
            } else {
                next()
            }
        } else {
            Vue.prototype.$notify({
                title: 'Tips',
                message: '请先登录!',
                type: 'error',
                duration: 3000
            })
            store.dispatch('clearCurrentState')  // 清空vuex
            next('/')
        }
    }
})

接口调用(重点登陆接口)

signinClcik:function(){
            // loginInfo 为参数
            userLogin(this.loginInfo).then( res => {
                if(res.data.code == 0){
                    // 获取 token 存入缓存 (重点!!!)
                    const token = res.data.token
                    window.localStorage.setItem('Token',token)
                    // 更新授权状态
                    this.$store.dispatch('setIsAuthenticated',true)
                }else{
                    this.$notify({
                        title: 'Tips',
                        message: res.data.message,
                        type: 'error',
                        duration:3000
                    })
                }
            })
         },
18、插槽的用法
作用:可复用的组件中,会给组件传递一些数据,为了让组件具有通用性,通常不能讲组件中的内容限制为divspan等元素,让使用者决定某一块区域存放的什么元素和内容

类型:定义组时,利用slot占坑 使复用组件的内容结构和数据动态话 => 增强组件的可复用性

1、默认插槽 => 子组件下不使用template写html‘结构
2、具名插槽 => 子组件标签下使用template => 包裹传递html结构 => template上提供名字 #插槽名  2、子组件通过传递数据 => 子传父
传入的标签可以分别派发给不同的slot位置
配合template使用,不回渲染到页面上,被解析为内部标签
3、作用域插槽

19、get和post的区别
1、语义 get获取资源,post提交数据给服务器
2、参数 get拼接在地址栏,post在请求体里
3、数据量 get受到浏览器的限制,两kb post不限制
4、安全性 get不如post安全
5、缓存 get会被浏览器自动缓存,post需要手动缓存
6、数据格式 get请求只能发送url编码的数据,post可以任意格式,和content-type匹配
20、winodw自带的事件监听属性
window的常见事件,方法,属性
1、事件:
onload:只有一次,当文档完全加载完成触发
可以使用事件监听的方式去注册事件
winodw.addEventlistener('name', function(){})
2、windoow.onResize() 调整窗口大小加载事件
3window.setTimeout()
4window.setIntervel()
三个对象:
location对象:用于获取或者设置窗体的url
location对象的参数
location对象的方法
1、location.assign()
2、location.replace()
3、location.reload()
navigator对象:包含浏览器的信息
history对象:与浏览器的历史记录进行交互,该对象包含用户在浏览器窗口中访问过的url
方法:
1、history.back
2、history.forward
3、history.go
21、this apply call bind
this是执行上下文的一个属性 指向调用这个方法的对象
三者区别:
都是改变this指向 第一个参数目标对象,null或undefined 指向window
参数: apply 数组 call 参数列表 bind 参数列表
返回:apply call只执行一次 立即执行 bind返回一个绑定this的函数

22、异步编程的方式
1、回调函数   回调地狱问题
2、promise   链式操作 耦合度高 不利于维护
3、generator
4、async await 将异步代码转为同步 执行到await的的时候,返回一个promise,等待promise的状态变为resolve的时候继续往下执行
23、promise
1、是异步的解决方案,是一个对象 可以获取异步操作的消息,链式操作避免了回调地狱
提供统一的api,任何操作都可以用同样的方法处理
2、实例状态:pending resolved rejected
3、实例过程:pending==》fullfiled完成 , rejected拒绝
4、特点:状态一旦发生改变无法再变
状态改变:then方法注册回调函数 resolve() reject()函数

async await 为了优化then链开发出来的 不会阻塞后面的语句
async await跟promise的区别:
不用传递中间值,是同步的写法
错误处理:try catch / promise错误捕获繁琐

24、对象的继承
1、
25、浏览器的渲染过程
1、根据html文档构建一颗dom树
2、css文件生成cssom规则树
3、结合这两者生成layout树
4、根据layout tree进行布局
5、绘制页面
6、显示到页面上
26、浏览器的内核
1、trident ie 安全问题
2、gecko 火狐 功能强大  内存消耗
3、presto opera 速度快 兼容问题
4、webkit safri 速度快 兼容问题
5、blink google
27、js错误处理
1.  语法错误

语法错误是最常见的 JavaScript 错误之一。这种错误通常发生在代码中存在语法错误的情况下。例如,如果你忘记在代码的某处添加分号或括号,就会出现此类错误。当代码执行到出现语法错误的位置时,它将停止并显示一个错误信息。为了解决语法错误,你需要仔细检查代码以找出错误所在的位置,并对其进行修正。

2.  类型错误

类型错误是另一个常见的 JavaScript 错误。它们通常发生在试图访问一个未定义或不存在的变量或方法时。例如,如果你尝试使用一个未定义的变量或方法,你就会出现类型错误。为了解决这种错误,你需要确保所有使用的变量和方法都已正确定义,并根据需要进行修改。

3.  运行时错误

运行时错误通常由代码中存在的逻辑错误引起。当代码执行时,它可能会引用一个不正确的变量或方法,导致代码执行出错并停止运行。为了解决这种错误,你需要仔细检查代码,找出逻辑错误,并对其进行修正。

4.  异步错误

异步错误是一种在代码中使用异步函数(如 AJAX 调用)时经常遇到的错误。这种错误可能会导致代码执行出错、数据丢失或应用程序的不正常行为。为了解决这种错误,你需要确保正确处理所有异步函数调用,并检查所有回调函数以确保捕获任何可能发生的错误。

5.  跨站点脚本(XSS)攻击

跨站点脚本攻击(XSS)是一种常见的安全漏洞。它可以通过注入有害的 JavaScript 代码来非法获取用户的用户数据或操作。为了解决这种错误,你应该采取一些安全措施来防止这种攻击,例如使用文本过滤器和配置内容安全策略。

最后,要注意的是,在编写 JavaScript 代码时,应遵循最佳实践和规范。使用易于阅读和理解的代码格式,正确使用注释和语法,以及避免使用过时或不安全的技术,这样可以显著减少代码中出现错误的可能性。

总之,JavaScript 错误在编写网页代码时是常见的。在面对这些错误时,应该通过检查代码、调试错误和使用最佳实践来解决它们。如果你是一名新手,向其他有经验的开发人员或设计师寻求帮助也是一个明智的选择。

h5

新增: canvas svg 特殊内容 语义元素:header footer nav article section 表单控件:date time calender email url search 表单属性: form:novalidate autocomplete input:autofocus required step placeholder 新增表单元素: datalist keygen output

新的技术:websocket, webworker

新的文档属性:document.visibilityState() 显示状态

地理定位:getcurrentposition()方法

存储:localstorage sessionstorage

移除的元素: s,u, basefont,big,center,font,strite,tt

对页面元素产生影响:frame,frameset,noframes

对h5语义化的了解: 正确的标签做正确的事 语义化让文档结构更加清晰,便于浏览器解析 在没有css的情况下也以文档格式显示 搜索引擎的爬虫也依赖于html的标记来区分上下文和各个关键字的权重,利于seo 利于维护者熟悉代码

css3

1、渐进增强,优雅降级 先满足低版本浏览器的需求,在此基础上构建页面,然后一步步向上兼容提升用户体验。 先在高版本的浏览器实现基本框架和功能,向下做适配。没定需求。

2、svg canvas的区别: canvas:绘制方式是像素,缩放失真 基于js svg:保存的是js的绘制方法,不失真 基于xml 每个元素都可以添加监听函数

各种图片格式之间区别:内容 质量 透明度 大小 jpeg: 有损,清晰度高,质量高,内容小,展示照片或者产品 png: 无损,透明度要求,质量比jpeg高,内容比他大 图标或标志 gif: 有损, webp: svg:

3、img的title、alt区别 title:鼠标划入提示文字 alt:等价描述,图片无法加载时显示

4、圆形的可点击区域 css:div设置属性border-radius:50%; js:文档点击事件判断点在不在上面;鼠标和圆的位置 html:area区域

5、page visibility api: 节省资源,减少电能消耗 对服务器轮询 网页动画 页面正在播放的音频或视频

6、实现浏览器多个标签页之间的通信 websocket:websocket入门 localstorage:监听

中介者模式
一个标签页websocket 主动推送
shareworker 共享线程
localstorage 监听事件
postmessage

7、iframe缺点: 创建一个包含其他文档的内联框架 back失效 onload事件阻塞 小型设备无法显示完整 搜索引擎无法解读,不利于seo

8、渲染页面的过程会遇到什么不良问题 白屏:页面css在文档底部后加载,页面先加载dom fouc:样式闪烁 js在文档顶部阻塞加载 css加载时间过长

9、优化渲染 关键资源的数量

10、css预处理器 scss less stylus 嵌套 变量 混入 mixins 函数 作用域 代码模块化

11、响应式 pc 平板 手机 视口决定内容显示的大小 媒体查询 百分比 vw/vh rem

12、两栏布局 四种 浮动 flex 定位(margin 定位 (left

13、三栏布局 五种 绝对定位+margin flex 浮动 圣杯(浮动+负边距) 父元素内边距padding 双飞翼(浮动+负边距) 子元素外边距margin

14、上中下布局 4 定位 flex grid table

es6的新增:

1、对象新增方法: object.is() 判断两个📄相等就返回true 区别在于 +0 和 -0 的区别,NAN不等于NAN

object.assign() 合并两个对象,前面的参数:目标对象(同名属性:后面覆盖前面的)
注意:nullundefined 无法转成对象 报错

用途:实现浅拷贝 对象添加属性 添加方法 克隆对象 浅拷贝 合并 默认值

object.getownpropertydescriptors() 返回对象所有属性描述对象

object.keys 返回数组:键名
object.values 返回数组:键值
object.entries 键值对数组 遍历对象的属性
object.hasown 判断是否为对象自身的属性

2、为什么0.1+0.2!== 0.3? js采用的是ieee754双精度标准,最多保留52位小数,二进制存储,两次存储时的精度丢失,一次计算丢失

解决精度丢失问题:先把小数转为整数,

3、对象的新增扩展: 函数的默认参数: length属性 函数的name 作用域 严格模式:如果函数使用了参数默认值,就不能设置内部为严格模式,否则报错 箭头函数: 指向:函数内指向定义时的对象 不可以new

4、为什么要模块化 什么是模块化: 能单独命名并且独立完成一定功能的语句的集合(程序代码的和数据结构的集合) 外部特征和内部特征: 外部跟内部的接口 内部的特点

为什么要模块化:
    独立的代码做独立的事
    代码抽象
    代码封装
    代码复用
    代码管理
    
难以维护,全局污染
逻辑复杂时代码难懂

1、git提交流程: git clone ssh://地址路径,http的地址(首次拉取输入账号) git add. 缓存区 git commit -m '' 本地提交 git pull git push origin test git push -u origin test

git checkout master 切换到master分支
git merge testtest上的代码合并到master)
git status
分支
git checkout -b name 创建并切换
git branch -d name

代码回滚:
git log #commit id
git reset --hard <commit id> 某个版本
git reset --hard HEAD^ 最新的一次提交


2、map 和 set 的区别 set:集合的数据结构 值,值 map:字典的数据结构

set array 区别

   1、元素重复
   2length跟size
   3、方法不一样 delete/splice has/indexof includes  获取元素 arr【index] set遍历
       push/add arr.length=0 clear()

3、跨域

jsonp:script标签的src属性,支持访问地址,提供回调函数来通讯
cors:前后端都要支持,后端设置: access-control-allow-origin * 所有
postmessage: 获取嵌入的第三方页面,postmessage发送,监听事件接收

4、项目开发流程

1、产品设计
2、原型评审
3、项目分工
4、项目开发
5、项目测试
6、项目构建
7、项目上线
8、后期维护

5、二次封装ajax

1、

6、ts跟js区别

js 动态类型 灵活
ts 静态类型 声明就是文档 维护方便
button()传不传参数 
js 
ts 重载概念 
vscode提示ts
ts 重构方便

7、项目 vue mvvm

8、上拉加载下拉刷新

移动端中 等同于pc的分页
hack:iscroll better-scroll pulltorefresh.js库

原生:本质页面触底
    scrolltop + clientheight >=offsettop
    

webpack: 1、为什么要使用模块化: 更高效的管理项目中的资源:将每个功能和相关数据放到同一个js文件下 问题:模块之间没有依赖关系,维护困难,以及项目扩大问题增加

2、解决:
   模块化
   高级的写法加快速率以及安全性
   监听文件变化并且反映到页面上
   js文件模块化,html,css同
   开发完成代码优化
   
3、静态模块打包工具
    编译代码(兼容)
    模块整合(性能)
    
 4、同webpack的工具
     rollup:速度快效率高,缺点导入模块需要借助插件
     parcel:自动安装依赖
     snowpack:单个文件构建
     vite:1、开发服务器:内建热更新
           2、构建指令:rollup打包代码,
     
            优点:冷启动 热更新(无需全部重新编译) 按需加载
            
     webpack优点: (一切皆模块 按需加载)
         1、智能解析:commonjs,es6,amd兼容
         2、万物模块:js,css,图片的打包
         3、开箱即用:hrm,tree-shaking
         4、代码分割:按需加载,初始化时间减少
         5、插件系统:plugin强大
         6、易于调试:SourceUrlsSourcemaps
         7、快速运行:异步执行
         8、生态丰富:解决问题容易
         
     热更新的原理:
         1、通过webpack-dev-server创建两个服务,提供静态资源服务的express和socket服务
         2、express直接提供静态资源,解析打包后的浏览器资源,及时更新
         3、socket是一个websocket的长链接,全双工通信
         4、socket监听文件变化,生成两个文件,manifest.json和.js文件(update chunk)
         5、使用长链接发送这两个文件到浏览器
         6、浏览器拿到后使用HMR runtime机制,加载这两个文件并且针对修改的文件更新
         
    提高构建速度:搜索时间降低,搜索范围缩小,减少不必要的编译
        1、优化loader配置  使用include,exclude匹配文件
        2、resolve.extensions  依赖拓展名
        3、resolve.modules  文件路径
        4、resolve.alias   文件别名
        5、dll.plugin   代码共享库
        6、cache-loader   缓存开销较大的loader
        7、terser多线程
        8、合理使用sourcemap
        
    常见的loader:
        (loader是什么:webpack分析各个模块之间的依赖关系并打包到指定的文件中,支持的是js和json文件,像import,require加载模块无法处理,需要用到相应的loader entry ==> loader ==> output)
        1、css-loader   分析个模块关系合成一个css
        2、style-loader  将css使用style形式放到文档的head
        3、less-loader   处理less文件
        4、raw-loader  import 的作用
        5、file-loader  将资源模块放到指定的输出目录,并返回在目录的地址
        6、url-loader  file-loader+ 图片处理 base-64的字符串并打包到js中
        
    webpack做过什么优化:
        1、开发效率、打包策略
            高版本webpack4.0
            分包优化:dllplugin,不常改动的代码静态化
            二次缓存:cache-loader babel-loader terser-webpack-loader
            多线程
            打包作用域缩小 include require define 语句的使用 ignoreplugin 
                loader规则 
                resolve-module 文件路径
                resolve-extension 文件后缀
                resolve-alias 文件别名
                
            
        2、打包速度过慢解决方案
            路由懒加载
            使用gzip压缩
            cdn引入js和css文件
            dllplugin将依赖的引用提取
            配置webpack的external,不打包第三方库
            
            利用webpack-bundle-analyser进行可视化分析看依赖和chunks大包的时间
                减少依赖嵌套深度
                使用尽可能少的处理
                dll第三方包的处理
                多线程 happypack
                关闭sourcemap
                extension配置
                alias
                modules配置
                include,exclude
                cache-loader
                eslint范围缩小
                webpack,node,npm的版本库更新
        
        3、优化性能
        (压缩)
            js:terserplugin
            css:css-minimizerplugin
            html: htmlwebpackplugin
            图片: mozjpeg, optipng, pngquant,gifsicle, webp
            文件: comperssionplugin
            tree-shaking: 消除死代码
                1、标记:usedexports
                2、跳过:sideeffects   直接跳过查看有无副作用
            代码分离:
            内联chunk:

网页性能优化: 1、懒加载:图片(scrolltop+innerheight>offsettop) 预加载:首屏优化, 2、预渲染:速度加快 link标签 rel=“prerender” 3、图片优化: 4、文件优化:

js手写代码

数字精度丢失 0.1 + 0.2 === 0.3 false

原因:计算机存储双精度浮点数需要先把十进制数转换为二进制的科学记数法的形式,然后计算机以自己的规则{符号位+(指数位+指数偏移量的二进制)+小数部分}存储二进制的科学记数法

因为存储时有位数限制(64位),并且某些十进制的浮点数在转换为二进制数时会出现无限循环,会造成二进制的舍入操作(0舍1入),当再转换为十进制时就造成了计算误差

当你拿到 1.4000000000000001 这样的数据要展示时,建议使用 toPrecision 凑整并 parseFloat 转成数字后再显示,如下:

parseFloat(1.4000000000000001.toPrecision(12)) === 1.4  // True

封装成方法就是:

function strip(num, precision = 12) {
  return +parseFloat(num.toPrecision(precision));
}
对于运算类操作,先转成整数后再运算
function add(num1, num2) {
  const num1Digits = (num1.toString().split('.')[1] || '').length;
  const num2Digits = (num2.toString().split('.')[1] || '').length;
  const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
  return (num1 * baseNum + num2 * baseNum) / baseNum;
}
防抖节流代码
    节流:使用定时器:设置一个定时器,并在delay时间后执行传入的函数func
            如果delay时间内触发,定时器还在,不执行传入的参数func。
            delay时间后执行函数并且清除定时器
        
    function throttle(func, delay) {
      let timer = null;
      return function(...args) {
        if (!timer) {
          timer = setTimeout(() => {
            func.apply(this, args);
            timer = null;
          }, delay);
        }
      };
    }

    // 使用节流优化滚动事件
    window.addEventListener('scroll', throttle(function() {
      console.log('scrolling...');
      // 计算滚动距离
    }, 500));
      
            
            
            
    防抖:使用定时器,事件触发时,先清除之前的定时器,在创建一个新的定时器,如果在delay期间多次触发,清除之前的定时器,重新创建一个定时器,知道delay时间内不在触发定时器定时器到达时间后执行事件并清除定时器。
    
    function debounce(func, delay) {
      let timer = null;
      return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(this, args);
        }, delay);
      };
    }

    // 使用防抖优化搜索框输入
    const searchInput = document.getElementById('search-input');
    const searchBtn = document.getElementById('search-btn');
    function search() {
      console.log('searching...');
      // 发送请求获取搜索结果
    }
    searchInput.addEventListener('input', debounce(search, 500));
    searchBtn.addEventListener('click', search);
    
    

![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3ff4be89037b4372a580b19947e04bff~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=996&h=656&s=129779&e=png&b=fbfdff)

image.png

数组扁平化
1、递归
function flat(arr){
  const isArray = arr.some(item => item instanceof Array);
  if(!isArray){
    return arr
  }
  const res = [].concat(...arr)
  return flat(res)
}
const res = flat([11,23,[23,2,2,21],[1,3,5,6]])
console.log(res);
2、循环
function flatten(arr) {
  while(arr.some(item => Array.isArray(item))){
    arr = [].concat(...arr)
  }
  return arr
}
数组去重
1、利用对象的属性不能重复
var newArr = []
arr.forEach((key,index)=>{
  if(newArr.indexOf(key) === -1){
    newArr.push(key)
  }
})
console.log(newArr);
2、new set(数组)
const newArr = [...new Set(arr)]
console.log(newArr);
3、map 同名键值对覆盖
const m = new Map()
for(var i=0;i<arr.length;i++){
  m.set(arr[i],arr[i])
}
const newArr = []
m.forEach((key,value)=>{
  newArr.push(value)
})
console.log(newArr);
4filter+indexof
5、reduce+includes
数组常用方法:
1、改变原数组  push pop unshift shift reverse sort splice
2、不改变原数组  concat join slice indexOf lastindexOf
3、es6新增  forEach map filter every some find(满足条件的第一个数据) reduce(叠加)
对象常用方法
object.js() 判断两个值是否相等
object.assign(target, ...source) 复制对象
object.entries() 属性
object.values() 值
object.prototype.hasownproperty() 是否有指定的属性作为自己的属性
object.prototype.toString() 对象的字符串
object.keys()
object.freeze(obj) 表示对象不能再被更改
ajax,fetch,axios的区别
1、都是请求数据的方法,但是维度不同
2、ajax是技术的统称,不是api
3、fetch是浏览器原生的api
4、axios是一个第三方库,可以直接使用

fetch:
和xmlhttprequest同一个级别
语法更加简单,易用,支持promise

ajax
技术统称。可以用xmlhttprequest实现 也可以用fetch实现

axios
网络请求库
可以简化http请求,新增一些高级功能
一些常用的方法
axios.all()
axios.spread
axios.cancelTooken()
axios.allSetteled()   都返回fullfilled

功能:
promise的api
拦截功能:
    axios.interceptor.request.use()
    axios.interceptor.response.use()
自动转换json数据
取消请求
跨域请求
默认请求 全局配置
node.js和浏览器支持
进度显示