css html
flex布局
display flex justify-content主轴对齐 align-items 交叉轴对齐 –wrap换行 –direction 主轴方向
垂直居中
flex justify-content align-items
清除浮动
浮动元素父元素高度自适应(父元素不写高度时,子元素写了浮动后,父元素会发生高度塌陷)
1. clear清除浮动(添加空div法)在浮动元素下方添加空div,并给该元素写css样式:{clear:both;height:0;overflow:hidden;}
2. 给浮动元素父级设置高度;
3. 父级同时浮动(需要给父级同级元素添加浮动);
4. 父级设置成inline-block,其margin: 0 auto居中方式失效;
5. 利用br标签的clear属性;
6. 给父级添加overflow:hidden 清除浮动方法;
7. 父级定义overflow:auto display:table
8. 父级div定义 伪类:after 和 zoom
9. 万能清除法 after伪类 清浮动(现在主流方法,推荐使用);
BFC 块级格式化上下文
可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
三栏布局
flex space-between
两栏布局
flex float calc(100vw – 500px)
动画 amimation
@keyframes 样式变更 -name 规定动画的名称 -iteration-count 运行多少次(infinite 无限) -direction 方向 - -timing-function 规定动画的速度曲线 -fill-mode 规定目标元素的样式
盒模型
标准content-box和怪异content-box 怪异盒模型是将padding和border包括在盒子的宽高内
width = content-width + padding-width + border-width content-height + padding-height + border-height
H5新特性
语义化标签 包括header footer vedio等 使标签可读性更强
rem em px rpx
px是相对于显示器屏幕分辨率而言的;
em的值并不是固定的;em会继承父级元素的字体大小
rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素
rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应;规定屏幕宽为750rpx
viewpoint是什么
viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,默认的viewport是layout viewport,也就是那个比屏幕要宽的viewport,但在进行移动设备网站的开发时,我们需要的是ideal viewport。
width=device-width表示当前的viewpoint等于设备的宽度,
width用来设置layout viewport的宽度,
height用来设置layout viewport的高度。
initial-scale=1.0表示页面的初始缩放值为1,
maximum-scale允许用户的最大缩放值,
minimum-scale允许用户的最小缩放值,
user-scalable表示是否允许用户缩放,“no”不允许,“yes”允许。
解释Flex布局,为什么要确定主轴方向,缩小倍数有什么用
flex 是 Flexible Box 的缩写,意为弹性布局 display:flex inline-flex
flex 2009 年就已出现,浏览器兼容性很好,请放心使用
块元素的垂直居中, flex 可以轻松解决
元素大小在容器中的自动伸缩,以适应容器的变化,特别适合移动端布局
确定主轴:主轴和侧轴是会变化的,就看flex-direction设置谁为主轴,剩下的就是侧轴,子元素是根据主轴来排列的
缩小倍数:子元素之间的相对大小可以通过缩小倍数来实现
javascript
继承
由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。所以,要想实现继承,可以用js的原型[prototype]机制或者用apply和call方法去实现
原型链
1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。
2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。
3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。
4、所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。
5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。
this指向
函数的this的最终指向的是那个调用它的对象 call bind apply可以改变this指向 我们通常使用箭头函数来规避各种因为this指向导致的问题
设计模式
原型模式 代理模式 观察者模式(发布订阅者模式)等
call, apply, bind 改变this指向
apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部列举出来 bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;:bind不会立即调用,其他两个会立即调用
new实现 new创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例
-
创建一个对象obj
-
obj.__proto__ = constructor.prototype(constructor 传入的对象)
3. 执行构造函数 并将构造函数作用域指向新对象 res = constructor.apply(obj, arg);(arg为传入的参数)
4. 如果该函数没有返回对象,则返回 this。( 实际是返回一个空对象, new Object()就是返回一个空对象{} )
防抖节流
函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。 防抖最后一次触发之后一定时间内执行 节流一定时间内执行一次
let, var, const 区别
let const块级作用域不会变量提升 var会变量提升 const定义基本数据类型不可变更 定义引用类型可变更
事件
event js事件对象 事件冒泡 事件捕获 事件委托 e.preventDefault() e.returnValue = false
loop 主线程、宏队列(macrotask)、微队列(microtask)
1、先执行主线程
2、遇到宏队列(macrotask)放到宏队列(macrotask)
3、遇到微队列(microtask)放到微队列(microtask)
4、主线程执行完毕
5、执行微队列(microtask),微队列(microtask)执行完毕
6、执行一次宏队列(macrotask)中的一个任务,执行完毕
7、执行微队列(microtask),执行完毕
8、依次循环。。。
promise使用及实现
异步编程的解决方案 解决回调地狱 解决异步 处理多个并发 pending resolve reject 状态不可变
all racepromise并行执行和顺序执行
闭包
函数内写函数 共享函数内的变量不会造成全局的变量污染 参数和变量不会被垃圾回收机制回收(会导致内存泄露)
垃圾回收和内存泄漏
浏览器的 Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。其原理是:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大并且GC时停止响应其他操作,所以垃圾回收器会按照固定的时间间隔周期性的执行。 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。Chrome自带的内存调试工具 在 Timeline -> Memory 查看内存使用和泄露情况 js中的内存泄露 循环引用 闭包 DOM泄露 定时器
数组方法
sort map foreach filter push pop shift unshift find some every concat
数组乱序
定义一个数组arr长度等于原数组 循环该数组arr 生成一个随机数i(0-原数组长度-1)作为下标 将arr[i]赋值给当前值 并原数组去掉当前arr[i]
数组扁平化
多维数组转为一维数组 flat
事件委托
多元素共有事件委托给其共同的父级元素 事件冒泡的应用
事件监听
addEventListener removeEventListener attachEvent 事件模型 捕获,目标,冒泡(e.stopPtopagation()) 注册事件addEventListener 和解除事件removeEventListener
Typescript
js的一个超集支持es6标准 TypeScript是为了使JavaScript的开发变得更加容易而创建的。 在日常的使用中体会到ts 类型批注和编译时类型检查
1. 类型推断
2. 类型擦除
3. 接口
4. 枚举
5. Mixin
6. 泛型编程
7. 名字空间
8. 元组
9. Await
http
HTTP1, HTTP2, HTTPS
HTTP 1.0短暂链接 请求后断开不跟踪不记录用户的请求 HTTP 1.1支持持久连接,允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,增加Host请求头字段,提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头,支持断点续传 1xx 已接受请求 2xx成功 3xx重定向 4xx客户端错误 通常指路径错误等 5xx服务端错误
HTTPS 加密的http HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。
( websocket http采用三次握手来建立连接,而websocket是基于http的,在第一次握手建立之后,websocket就建立了长久的链接,只有当有一方关闭连接时才关闭)
浏览从输入网址到回车发生了什么?
在浏览器中输入网址按回车发生的事件:
(1)进行DNS解析(域名解析),获取Web服务器的IP地址。
(2)建立TCP连接。
三次握手过程:
第一次握手:客户端向服务器端发送请求,等待服务器确认。
第二次握手:服务器收到请求并确认,回复一个指令。
第三次握手:客户端收到服务器的回复指令并返回确认。
(3)向Web服务器发送HTTP请求。
(4)Web服务器接收到请求并处理。
(5)Web服务器返回响应。
(6)浏览器对响应进行解码,并显示数据。
(7)页面显示完成后,浏览器发送异步请求。
(9)关闭TCP连接。
前端跨域
浏览器同源策略限制的一类请求场景 同源指的是 协议+域名+端口相同
解决跨域:
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
浏览器缓存
cookie 客户端存储 不能超过4K ,
session 服务端存储,
token身份认证token安全性比session好 ,
localstorage, sessionstorage和cookie:
都是保存在浏览器端,且都遵循同源策略。localStorage本地持久化存储 手动删除 sessionstorage窗口级存储 窗口关闭即删除 cookie一般由服务器生成,可设置失效时间,如果在浏览器端生成cookie,默认关闭浏览器后失效。cookie大约在4k左右,localStorage和SessionStorage一般为5MB左右。
状态码
2xx成功 3xx重定向 4xx客户端错误 通常指路径错误等 5xx服务端错误
TCP连接(三次握手, 四次挥手)
三次握手:
第一次握手:客户端向服务器端发送请求,等待服务器确认。
第二次握手:服务器收到请求并确认,回复一个指令。
第三次握手:客户端收到服务器的回复指令并返回确认。
四次挥手:
第一次挥手:客户端发送一个FIN连接终止位,用来关闭客户到服务器的数据传送。
第二次握手:服务器收到这个FIN,它发回一个ACK确认报文段,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
第三次握手:服务器B关闭与客户端A的连接,发送一个FIN给客户端。
第四次握手::客户端发回ACK报文确认,并将确认序号设置为收到序号加1。
浏览器渲染过程
1. 构建dom树
a) DOM树在构建的过程中可能会被CSS和JS的加载而执行阻塞
b) display:none的元素也会在DOM树中
c) 注释也会在DOM树中
d) script标签会在DOM树中
2. 构建CSSOM树 a) CSS解析可以与DOM解析同时进行。
b) CSS解析与script的执行互斥。
c) 在Webkit内核中进行了script执行优化,只有在JS访问CSS时才会发生互斥。
d) js脚本的出现会让CSSOM的构建阻塞DOM的构建
3. 将DOM和CSSOM合并为渲染树(rendering tree)
a) Render Tree和DOM Tree不完全对应
b) display: none的元素不在Render Tree中
c) visibility: hidden的元素在Render Tree中
4. 布局
a) float元素,absoulte元素,fixed元素会发生位置偏移。
b) 我们常说的脱离文档流,其实就是脱离Render Tree。
5. 绘制
前端缓存 接口端的缓存
-
缓存位置 缓存的位置按照获取资源请求优先级,缓存位置依次如下:
n Memory Cache(内存缓存)内存空间比较小,通常较小的资源放在内存缓存中,比如 base64 图片等资源 n Service Worker(离线缓存)可以帮我们实现离线缓存、消息推送和网络代理等功能 n Disk Cache(磁盘缓存)内存的优先性,导致大文件不能缓存到内存中,那么磁盘缓存则不同。虽然存储效率比内存缓存慢,但是存储容量和存储市场有优势 n Push Cache(推送缓存)属于 HTTP2 的内容
HTTP 缓存分为 2 种,一种是强缓存,另一种是协商缓存。主要作用是可以加快资源获取速度,提升用户体验,减少网络传输,缓解服务端的压力。
强缓存 不需要发送请求到服务端,直接读取浏览器本地缓存
-
Expires Expires 的值是一个 HTTP 日期,在浏览器发起请求时,会根据系统时间和 Expires 的值进行比较,如果系统时间超过了 Expires 的值,缓存失效。
-
Cache-Control Cache-Control 是 HTTP/1.1 中新增的属性,在请求头和响应头中都可以使用,常用的属性值如有:
max-age:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效 no-cache:不使用强缓存,需要与服务器验证缓存是否新鲜 no-store:禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源 private:专用于个人的缓存,中间代理、CDN 等不能缓存此响应 public:响应可以被中间代理、CDN 等缓存 must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证 -
Pragma只有一个属性值,就是 no-cache ,效果和 Cache-Control 中的 no-cache 一致,不使用强缓存,需要与服务器验证缓存是否新鲜,在 3 个头部属性中的优先级最高
协商缓存
当浏览器的强缓存失效的时候或者请求头中设置了不走强缓存,并且在请求头中设置了If-Modified-Since 或者 If-None-Match 的时候,会将这两个属性值到服务端去验证是否命中协商缓存,如果命中了协商缓存,会返回 304 状态,加载浏览器缓存,并且响应头会设置 Last-Modified 或者 ETag 属性。
ETag/If-None-Match 一串 hash 码,代表的是一个资源的标识符,当服务端的文件变化的时候,它的 hash码会随之改变,通过请求头中的 If-None-Match 和当前文件的 hash 值进行比较,如果相等则表示命中协商缓存 hash 码是以 "W/" 开头的一串字符串,说明此时协商缓存的校验是弱校验的
Last-Modified/If-Modified-Since 代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存
回流和重绘
reflow(回流)结构发生了变化 比如增加减少了dom 布局结构发生了改变
a) 页面第一次渲染(初始化)
b) DOM树变化(如:增删节点)
c) Render树变化(如:padding改变)
d) 浏览器窗口resize
e) 获取元素的某些属性
repaint(重绘)改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变
a) 背景色、颜色、字体改变(注意:字体大小发生变化时,会触发回流)
减少回流和重绘
1. 用transform做形变和位移可以减少reflow
2. 避免逐个修改节点样式,尽量一次性修改
3. 使用DocumentFragment将需要多次修改的DOM元素缓存,最后一次性append到真实DOM中渲染
4. 可以将需要多次修改的DOM元素设置display:none,操作完再显示。(因为隐藏元素不在render树内,因此修改隐藏元素不会触发回流重绘)
5. 避免多次读取某些属性
6. 通过绝对位移将复杂的节点元素脱离文档流,形成新的Render Layer,降低回流成本
优化渲染
1. 合法地去书写HTML和CSS ,且不要忘了文档编码类型。
2. 样式文件应当在head标签中,而脚本文件在body结束前,这样可以防止阻塞的方式。
3. 简化并优化CSS选择器,尽量将嵌套层减少到最小。
4. DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。
5. 如果某个样式是通过重排得到的,那么最好缓存结果。避免下一次用到的时候,浏览器又要重排。
6. 不要一条条地改变样式,而要通过改变class,或者csstext属性,一次性地改变样式。
7. 尽量用transform来做形变和位移
8. 尽量使用离线DOM,而不是真实的网页DOM,来改变元素样式。比如,操作Document Fragment对象,完成后再把这个对象加入DOM。再比如,使用cloneNode()方法,在克隆的节点上进行操作,然后再用克隆的节点替换原始节点。
9. 先将元素设为display: none(需要1次重排和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次重排和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。
10. position属性为absolute或fixed的元素,重排的开销会比较小,因为不用考虑它对其他元素的影响。
11. 只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响重排和重绘。另外,visibility : hidden的元素只对重绘有影响,不影响重排。
12. 使用window.requestAnimationFrame()、window.requestIdleCallback()这两个方法调节重新渲染。
# react相关
函数式编程Functional Programming,简称FP
函数式编程更加强调程序执行的结果而非执行的过程;react就是最经典的FP ReactView = render(data) 它只关心你的输入,最终给你返回相应视图。几个特性
1. 函数可以跟其他变量一样,可以作为其他函数的输入输出
2. 纯函数
3. 引用透明 同样的输入,必定是同样的输出。函数内部不依赖外部状态
4. 惰性计算 一个表达式绑定的变量,不是声明的时候就计算出来,而是真正用到它的时候才去计算
FP在JavaScript中的优势
优势:更好的状态管理 组合灵活 复用性高 可维护性好
React的Diff原理
分层同层比较 key保证唯一性 可以通过生命周期提升性能
(1) 把树形结构按照层级分解,只比较同级元素。\
(2) 列表结构的每个单元添加唯一的 key 属性,方便比较。\
(3) React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)\
(4) 合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.\
(5) 选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
Fiber解决什么问题
借此可改进浏览器端和其他渲染设备的响应速度。简单来说,此时不在需要等待变更传播到整个组件树,React Fiber 可以知道如何时不时暂停一下,检查是否有其他更重要的更新。这种调度能力主要基于 [requestIdleCallback]的使用,而这是一种 [W3C 候选推荐标准]。
能够将可中断的任务拆分成块。
能够对进程中的工作划分优先级、重新设定基址(Rebase)、恢复。
能够在父子之间来回反复,借此为 React 的 Layout 提供支持。
能够通过 render() 返回多个元素。
为错误边界提供了更好的支持。
时间分片的大概原理
时间分片 React在挂载或者更新过程中会做很多事情,比如调用组件的渲染函数、对比前后树差异,而且commit阶段是同步的,所以在Stack Reconciler中会导致卡顿等问题。
setState原理
react的异步操作 变更页面的state以达到重新渲染页面的目的 异步操作 支持回调函数的写法 多个setState操作会优化执行
webpack
webpack的构建流程
初始化—编译—输出 Webpack在启动后,会
从Entry开始,递归解析Entry依赖的所有Module,
每找到一个Module,就会根据Module.rules里配置的Loader规则进行相应的转换处理,
对Module进行转换后,再解析出当前Module依赖的Module,
这些Module会以Entry为单位进行分组,即为一个Chunk。
因此一个Chunk,就是一个Entry及其所有依赖的Module合并的结果。最后Webpack会将所有的Chunk转换成文件输出Output。在整个构建流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑,从而完成Plugin插件的优化任务。
plugins和loader的区别
什么是loader?
Loader用于对模块文件进行编译转换和加载处理,在module.rules数组中进行配置,它用于告诉Webpack在遇到哪些文件时使用哪些Loader去加载和转换。Loader还可以通过querystring或object指定选项参数。内部钩子
什么是plugin?
Plugin用于扩展Webpack功能,实现原理是在构建流程里注入钩子函数。在plugins数组中进行配置。注入的钩子
1. 两者都是为了扩展webpack的功能。loader它只专注于转化文件(transform)这一个领域,完成压缩,打包,语言翻译; 而plugin不仅只局限在打包,资源的加载上,还可以打包优化和压缩,重新定义环境变量等
2. loader运行在打包文件之前(loader为在模块加载时的预处理文件);plugins在整个编译周期都起作用
3. 一个loader的职责是单一的,只需要完成一种转换。一个loader其实就是一个Node.js模块。当需要调用多个loader去转换一个文件时,每个loader会链式的顺序执行
4. 在webpack运行的生命周期中会广播出许多事件,plugin会监听这些事件,在合适的时机通过webpack提供的API改变输出结果
webpack构建优化方式有哪些
更精准的loader规则
更精准的查找目录
指定哪些文件不通过loader处理,或者指定哪些文件通过loader处理
更精准的扩展名
使用动态链接库预编译大模块
多进程处理文件(使用HappyPack同时处理多个loader编译任务)
多进程压缩文件 使用ParallelUglifyPlugin多进程同时压缩文件
减少监听文件
第三方库映射
webpack的分包策略
4.x以前 CommonsChunkPlugin 4 以后 optimization.splitChunks
新的 chunk 是否被共享或者是来自 node_modules 的模块
新的 chunk 体积在压缩之前是否大于 30kb
按需加载 chunk 的并发请求数量小于等于 5 个
页面初始加载时的并发请求数量小于等于 3 个
webpack优化配置
打包优化
-
cdn 分包 -
多进程构建(thread-loader HappyPack parallel-webpack) -
并行压缩 -
预编译资源模块 -
使用缓存 - 使用 webpack5 内置的 cache 模块 - cache-loader(webpack5内置了 cache 模块后可弃用 cache-loader)
6 缩小构建范围 通过合理配置 rules 中的文件查找范围,可以减少打包的范围,从而提升打包速度。 7 加快文件查找速度 通过合理配置 webpack 的 resolve 模块,可以加快文件的查找速度
打包体积优化
体积分析
提取公共模块
压缩代码
-html 压缩
- css 压缩
- js 压缩
图片压缩
移除无用的 css
polyfill service 采用 polyfill service 方案,它能够识别 User Agent,下发不同的 polyfill,做到按需加载需要的 polyfill,从而优化我们项目的体积
开发环境和生产环境的webpack配置区别
开发环境:开发人员调试开发的一种环境: 方便调试,保持高效的开发
模块热更新 (本地开启服务,实时更新)
sourceMap (代码映射,方便打包调试)
接口代理 (配置proxyTable解决开发环境中的跨域问题)
代码规范检查 (代码规范检查工具)
生产环境:发布上线的环境: 让程序在生产环境中正常有效的运行
提取公共代码
压缩混淆(压缩混淆代码,清除代码空格,注释等信息使其变得难以阅读)
文件压缩/base64编码(压缩代码,减少线上环境文件包的大小)
去除无用的代码
开发环境和生产环境的共同需求:
入口
代码处理(loader处理)
解析配置
项目优化
项目优化都做了哪些操作
加载优化(减少http请求数)
图片优化
使用CDN
开启Gzip(代码压缩)
减少不必要的Cookie
脚本优化
前端代码结构的优化
SEO优化
react 函数组件和class的区别和优劣 为啥要使用函数组件
1. 组件定义方式不同
2. (因为组件定义方式不同)生命周期不同:class组件有,函数组件无;
3. (因为生命周期不同)副作用操作执行不同:class组件通过生命周期函数,函数组件用hook的useEffect;
4. state的定义、读取、修改方式不同:函数组件用hook的useState;
5. this:class组件有,函数组件无;
6. 实例:class组件有,函数组件无;
7. (因为实例不同)ref使用不同:class组件有,函数组件无;
使用上: 官方推荐函数组件。
useEffect和 useLayoutEffect的区别 什么时候使用
相同点:都是在函数更新后执行,使用的方法也相同
不同点:useEffect 是在dom更新后异步执行 。useLayoutEffect 是在dom更新前同步执行(有可能会阻塞dom渲染),执行完再更新dom。useLayoutEffect可以解决更新dom时候屏幕闪烁的问题
离线包原理
-
H5/CSS/JS和资源文件打包提前下发到App中,这样App在加载网页的时候实际上加载的是本地的文件,减少网络请求来提高网页的渲染速度,并实现动态更新效果
通过获取沙盒H5路径直接加载 基于NSURLProtocol进行请求拦截 基于WKURLSchemeHandler进行自定义scheme注册拦截 起本地服务器加载本地资源
前端架构的理解
代码 归根结底,所有的网站都是由一堆文本文件和资源文件组成HTML、CSS、JavaScript的。当我们面对制作网站所产生的大量代码时,就会发现为代码和资源设定一个期望是多么重要。
流程 怎么用工具和流程构建一个高效且避免出错的工作流是一个重要的思考。工作流变得越来越复杂,那些用于构建它们的工具也同样如此。这些工具在提高生产力、加快效率和保持代码一致性上带来了惊人的效果,但也伴随着过度工程化和抽象化的风险。
测试 要构建一个可扩展和可持续优化的系统,必须保证新代码与老代码能够很好地兼容,我们的代码不会孤立存在,它们都是大型系统中的一部分,创建覆盖面广泛的测试方案,能确保老代码还能正常运行。
文档 设计文档是你同他人交流的工具,来阐述你的设计决策是什么,来阐明你的设计决策是什么以及为什么你的决策是好的。如果不是团队中的重要成员要离开,几乎都不会意识到文档的重要性。
算法题(持续收录)
给一个字符串,循环输出每一个字符,当输出到最后一个字符时再从头开始
function print(str){
let i = 0 ;
return function(){
if(i===str.length) {i = 0};
let res = str[i];
i+=1;
return res;
}
}
给一个数,判断该数是否是斐波那契数列里的一项,若是则返回第几项,若不是则返回-1
斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...
这个数列从第3项开始,每一项都等于前两项之和。
function judgeNumber(num){
let a =1 ,b = 1,sum = 0,idx= 1,
while(sum<num){
sum = a+b;
[a,b]=[b,sum];
idx+=1;
}
return sum===num ? idx : -1;
}
实现链式的加减乘除(myCalculator(1).add(12).minus(3).multi(10).div(5).getValue() === 25)
链式,按.调用方法,联想到类的知识点,因为实例调用类中的方法就是按.调用的,调用完后再返回this,也就相当于计算完后,又把实例返回了,可以继续调用方法
function myCalculator(num) {
class Cal {
constructor(val) {
this.value = val
}
getValue() {
return this.value
}
// 加法
add(newVal) {
this.value = this.value + newVal
return this
}
// 减法
minus(newVal) {
this.value = this.value - newVal
return this
}
// 乘法
multi(newVal) {
this.value = this.value * newVal
return this
}
// 除法
div(newVal) {
this.value = this.value / newVal
return this
}
}
const obj = new Cal(num)
return obj
}
搜索多个文件夹路径(字符串数组,例如['/usr/bin', '/etc/config']),查找是否有公共路径,若有则返回公共路径(字符串),否则返回 null
function commenPath(urlArr){\
// 获取一个路径名的二维数组
const newArr = urlArr?.map(item=>{
return item.split('/')?.filter(val=>val);
});
// 定义一个空数组 存放满足的条件的路径名
const common =[];
newArr.forEach(item=>{
item.forEach((val,idx)=>{\
// 判断当前在路径数组的每一个位置是否都存在
const flag = newArr.every(i=>i[idx]===val);
if(flag) {
// 如果存在则将其存入数组中 会有重复的push
common.push(val);
}
})
})
console.log(common)
// 判断数组长度是否大于0 因为可能有相同项 所以需要去重后在拼接 首位需要手动补一个/
return common?.length>0? ’/’+ [...new Set(common)].join('/') : null
}
若a * a + b * b === c * c,则称'a,b,c'为勾股数,找出比 n 小的所有勾股数
function gougu(n) {
let arr = []
// 最小的勾股数为3,所以弦最小为5 a为勾最小 b为股 c为弦
for (let c = n; c >= 5; c--) {
let b = c-1,a = 3
while(b>a){
if(a*a+b*b===c*c){
arr.push(`${a},${b},${c}`)
b--
a++
}else if(b*b+a*a>c*c){
b--
}else{
a++
}
}
}
return arr
}
给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。 找到所有出现两次的元素。
findDuplicates = function(nums) {
let result = [];
for (let i = 0; i < nums.length; i++) {
let num = Math.abs(nums[i]);
if (nums[num - 1] > 0) {
nums[num - 1] *= -1;
} else {
result.push(num);
}
return res;
};
找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
const findRepeatNumber = function(nums) {
for(let i = 0;i<nums.length;i++){
while(nums[i]!==i){
if(nums[nums[i]] !== nums[i]){
const temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}else{
return nums[i]
}
}
}
return -1;
};