新年学习的第一天(摘抄)

83 阅读8分钟

学习内容

1月1日

水平垂直居中方案

1.     flex居中

2.     绝对定位+margin auto居中

3.     绝对定位+Transform居中

隐藏元素

1.     display:none

2.     opacity:0

3.     visibility:hidden

typeof与instanceof

1.     typeof识别所有的值类型,识别函数,能区分是否是引用类型

2.     instanceof用于检测构造函数的prototype 属性是否出现在某个实例对象的原型链上

数组的方法及作用

1.     forEach是对数组的每一个元素执行一次给定的函数

2.     map是创建一个新数组,该新数组由原数组的每个元素都调用一次函数的返回值

3.     pop删除数组的最后一个元素,返回被删除的元素

4.     push将一个或多个元素添加至数组的末尾,并返回数组的长度

5.     shift删除数组的第一个元素,并返回删除元素

6.     unshift将一个或多个元素添加至数组开头,并返回数组长度

7.     splice通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组的形式返回被修改的内容

8.     rerverse反转数组

闭包和作用域

闭包是作用域应用的特殊场景,js的常见作用域包括全局作用域、函数作用域、块级作用域。

常见闭包的使用常见:函数作为参数被传递、函数作为参数被返回。

手写new关键字

在js中new关键字主要做了:创建空对象,对象会作为执行new构造函数之后返回的对象实例,将指向空对象的原型指向构造函数的prototype属性,同时将空对象复赋值给函数内部的this。并执行构造函数的逻辑,返回初始创建的对象或构造函数的显性返回值。

箭头函数和普通函数的区别

箭头函数不会创建自身的this,只会从上一级继承this,箭头函数的this在定义时就已经确定,之后就不会更改。同时箭头函数无法作为构造函数使用,没有自身的prototype,也没有arguments。

迭代器与生成器的关系

任意一个对象实现了遵守迭代器协议的[Symbol.iterator]方法,那么该对象就可以调用[Symbol.iterator]返回一个遍历器对象。生成器函数就是遍历器生成函数,故可以把生成器赋值给对象的[Symbol.iterator]属性,从而使该对象具有迭代器接口

浏览器事件循环机制

Js是单线程(同一时间只能干一件事),同时还是非阻塞运行的(执行异步任务时,会挂起相应任务,待异步返回结果再执行回调)。

在js执行代码时,会将对象储存在堆中,在栈中记录对象在堆中的地址值,同时还会记录基础数据类型变量。

type与interface区别

interface可以重复声明,type不行。

继承方式不同,type使用交叉类型方式&,interface使用extends实现。在对象扩展的情况下,使用接口继承要比交叉类型的性能更好。建议使用interface来描述对象对外暴露接口。使用type将一组类型重命名。

Any、unkonwn、never

any与unkonwn在TS类型中属于顶层TopType,即所有的类型都是他们的子类型。而never则相反,它作为Bottom type是所有类型的子类型。

       常见工具类型:

1.     Partial:满足部分属性即可

2.     Required:所有属性都需要

3.     Readonly:包装后所有属性只读

4.     Pick:选取部分属性

5.     Omit:去除部分属性

6.     Extract:交集

7.     Exclude:差集

虚拟Dom

采用虚拟DOM的更新技术在性能上理论上不可能比原生js操作DOM高。开发者很难写出绝对优化的命令式代码。所以虚拟DOM就是用来解决这一问题,让开发者在代码的性能上得到保障,甚至无限接近命令式代码的性能。

1.     vue2中使用的是双端·diff算法:是一种同时比较新旧两组节点的两个端点算法(比头、比尾,头比尾、尾比头)。

2.     vue3中使用快速diff算法:它借鉴文本diff算法的预处理思路,先处理新旧两组节点中相同的前置节点和后置节点。当全部处理完毕后进行比对,构建一个最长递增子序列。

Vue3双向绑定的实现

Vue3实现双向绑定的核心是Proxy(代理),它会对需要响应式处理的对象进行一层代理,对象的所有操作都会被Proxy代理。

Vue中ref、toRef、toRefs

1.     ref接受一个内部值,生成对应的响应式数据,该内部值挂载在ref对象的value属性上。

2.     toRef为响应式对象的一个属性创建对应的ref。

3.     toRefs将响应式对象转换成普通对象

浏览器渲染页面的过程

首先输入网址,浏览器会向服务器发起DNS请求,得到相应的IP地址,之后进行tcp三次握手与服务器建立连接,连接建立后,浏览器会代表用户发送一个初始的GET请求,通常是请求HTML文件。服务器收到对应请求后,会根据相关的响应头和HTML内容进行回复。

       一旦浏览器拿到数据,机会开始解析信息,这个过程浏览器会根据HTML文件构建DOM树,当遇到同步资源,会停止DOM树生成,执行同步资源。在构建DOM树时,浏览器主线程是被占据的,不过浏览器的预加载扫描器会去请求高级优先级的资源,预加载扫描器很好的解决了单线程的阻塞问题。接下来浏览器会处理css生成cssDOM树,将css规则转换为可以理解和使用的样式映射。当有了DOM树和cssDOM树,浏览器会将其组合生成一个render树,计算样式或渲染树会从DOM的根节点开始构建。遍历每一个可见节点(将相关的样式匹配到每一个可见节点上),接下来开始布局,该过程(依旧从根节点开始)会确定所有节点的宽高位置,通过渲染器将其绘制在页面上。绘制完成了并不代表交互也都生效了,因为主线程可能还无法抽出时间去处理滚动、触摸等交互,要等到js加载完成,同时主线程是空闲状态。

Webpack优化方案

基于esm的tree shaking

对babel设置缓存,缩小babel-loader的处理范围,及精准指定要处理的目录。

压缩资源

配置资源的按需导入

设置CDN优化

前端权限设计思路

项目中,尤其是管理后台必不可少的一个环节就是权限设计。通常一个系统的不同用户会对应不同的角色,不同角色对应不同组织。在进入管理后台的时候会去请求对应的权限接口,这个接口是与后台约定好的权限标识内容。

什么情况会重绘和回流

浏览器请求对应页面资源时,会将HTML解析为DOM树,CSS解析成CSSOM树,然后将DOM树与CSSOM树合并产生render树,浏览器根据render树计算节点在页面的位置大小,最后将节点绘制在页面上。

       当render tree中部分或全部元素的尺寸、结构、属性发生变化,浏览器就会重新渲染页面,这个就是浏览器的回流。

       当页面的元素样式的改变不影响它在文档流的位置时(颜色变化),这就是重绘。

回流必定导致重绘,重绘不一定会引起回流,回流比重绘代价更高。

 

常见改善方案:

1.     在频繁进行操作时,可以使用防抖和节流来控制频率。

2.     避免频繁的操作DOM

3.     复杂动画可以使用绝对定位,脱离文档流,否则他会频繁引起父元素及其后续元素的回流

大量数据如何优化

大量数据使用异步接收,对数据进行分片处理,渲染如果是采用长列表,可以使用虚拟列表(当前页面需要渲染的数据进行渲染,监听交互事件来切换渲染数据)

手写深拷贝

Function deepClone(obj){                  

       //判断是否是对象以及是否为null,不是对象直接返回

       if(typeof obj !== “object” || obj === null) obj

       //创建返回值的对象,并对值进行初始化   Object and Array

       const result = obj instanceof Array ? [] : {}

       //遍历对象,如果属性值还是对象,递归调用函数

       forconst key in obj){

              if(obj.hasOwnProperty(key)){

                     result[key] = deepClone(obj[key])

}

}

return result

}
手写防抖与节流函数
//防抖函数

function(fn,delay){

       let timer

       return function(){

              if(timer){

                     clearTimeout(timer)

}

timer = setTimeout(()=>{

       fn,apply(this,arguments);

timer = null

},delay)

}

}

//节流

function(fn,delay){

       let timer;

       return function(){

              if(timer) return

              timer = setTimeout(()=>{

                     fn.apply(this,arguments);

                     timer = null

},delay)

}

}