一面
曾经做过的最有挑战的一个项目
DOM 的事件机制,怎么阻止事件捕获
dom事件由事件源(发生在哪)、事件类型(什么动作)、事件处理程序(回调)三部分组成。阶段分为捕获阶段(自document起向下到目标元素)、目标阶段(事件在目标元素上发生并处理。但处理会被看成是事件冒泡阶段的一部分。(接收事件、触发事件))和冒泡阶段(从目标元素向上到传递回document)。
常用的 ES6 语法有哪些,var 怎么实现let
*const let 解构赋值 set map promise async await
var 会变量提升,声明前可访问到默认值undefined定义未赋值,let 存在暂时性死区,提前读取报错提示未定义。for 循环中,var 声明的变量会污染作用域,读值只能读到最后循环完成时的变量值。let 可以正常访问没一轮
可以利用闭包实现
let arr = []
for (let i = 0; i < 3; i++) {
arr[i] = function () { console.log(i) }
}
arr[0]() // 0 arr[1]() // 1 arr[2]() // 2
var arrV = []
for (var i = 0; i < 3; i++) {
arrV[i] = function () {
console.log(i)
}
}
// 循环完毕,此时i等于3,故每次输出都为3
arrV[0]() // 3
arrV[1]() // 3
arrV[2]() // 3
var a = []
for (var i = 0; i < 3; i ++) {
(function () {
var b = i
a[i] = function() {
// 注意不能直接输出i,不然依旧一样
console.log('i为:' + i)
console.log('b为:' + b)
}
}) (i)
}
a[0]() // i为3,b为0
React Hooks vs Component
hooks 是解决函数式组件生命周期和不能使用状态的函数式实现包括useState useEffect(componentDidMount、componentDidUpdate 和 componentWillUnmount) useContext useReducer
(Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。 React Hooks 就是那些钩子)
Component 是class组件让人困惑 同样的事情可能componentdidmount 和 componentdidupdate都在做,this指向会出现问题;监听注册和取消在didmount 和 willunmount,不方便;共用逻辑难以抽离
React中的 useCallback 和 useMemo 有什么区别,什么情况下需要用 useCallback
我自己以为:useCallback用于缓存函数,useMemo用户缓存值的。如果一个方法或值并不依赖上层组件的更新而更新,就可以用到这两个针对性对props或者state进行监听并作出相应的更新
useCallback:返回一个 memoized 回调函数。在依赖参数不变的情况下,返回的回调函数是同一个引用地址 (解决匿名函数总是地址不同的问题
useMemo:返回一个 memoized 值。在依赖参数不变的的情况返回的是上次第一次计算的值
参考:juejin.cn/post/684490…
浏览器的 Event Loop 机制
~~我感觉:由于js是单线程的性质,因此为了避免异步等待,开发出函数执行栈、任务队列。~~主线程代码在运行时,会按照同步代码、异步代码将其分成两个去处,同步代码->直接将该任务放入函数执行栈进行执行,先进后出按序进栈。异步代码放到工作线程。【工作线程】保存的是定时任务函数、JS交互事件、js的网络请求等耗时的工作。当主线程将代码块筛选完毕后,进入执行栈的函数会按照从顶向下的顺序依次运行,运行中涉及到的对象数据是在堆内存中进行保存和管理。当执行栈内任务全部执行完毕后,执行栈就会晴空。清空后,"事件循环"就会检测【任务队列】中是否有要执行的任务。这个任务队列的任务来源就是工作线程,程序运行期间,工作线程会把到期的定时任务、返回数据的http任务等【异步任务】按照先后顺序插入到任务队列中,等执行栈清空后事件循环会访问任务队列,将任务队列中存在的任务,按顺序(先进先出)放入执行栈,继续执行,直到任务队列清空
setState 是同步还是异步的
setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步 。(因为会收集更新一起批量更新,这种优化手段和行为展示有时候表现像异步,其实本身不是的。)
Set 的用法,用 Set 实现数组去重
[...new Set(arr)] Set去充再结构赋值到新数组
Graphql 的使用
graphql.cn/ segmentfault.com/a/119000001…
移动端适配方案, rem 和 em 的区别
rem相对于根元素root的字体大小,em相对于当前元素的字体大小
React 解决了什么问题
我觉得:解决了动态渲染时大量直接操作dom的造成用户体验不好的弊端。通过虚拟dom和diff算法进行局部渲染,借助细小的fiber进行协调reconciliation和commit达到增量式渲染的目的
前端跨域怎么做
jsonp src img script iframe
编程题:用 setTimeout 实现 setInterval
//我理解的意思
timerFunc();
function timerFunc(){
let timer=setTimeout(function(){
timerFun();
clearTimeout(timer)
},1000);
}
//两种
window.idarr = [0];
function _setInterval(fun, time) {
var id = setTimeout(function() {
_setInterval(fun, time);
fun();
clearTimeout(id);
}, time);
window.idarr.pop();
window.idarr.push(id);
return window.idarr;
}
function _clearInterval(id) { clearTimeout(id[0]); }
less-loader 的 less 转成 css 的底层原理
*不会,
本质上,LESS 包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的 CSS 文件 ?
note: since less is a superset of css, nodes not possible in less(e.g extend) are slowly transformed into css\
// 意思大概就是less是css的超集,因此在less中转换为css节点是比较慢的
原理主要分析:
less 是预编译处理器,所以会在编译前进行处理成css
- 首先less 会转换为ast(抽象语法树)语法
- 然后遍历转换后所有的节点
- 最后再形成css树
链接:www.jianshu.com/p/4eb1fe53c… *
webpack的 loader 和 plugin 区别
功能不同,loader编译器,编译解释作用,less sass 转成css,urlloader fileloader文件处理等
plugin插件,loader不提供的能力需要通过社区plugin自己做,压缩,html生成,缓存
webpack 常用插件\
- OptimizeCSSPlugin UglifyJsPlugin CopyWebpackPlugin HtmlWebpackPlugin CompressionWebpackPlugin ExtractTextPlugin抽离css CommonsChunkPlugin(三方库chunk)【插件的主要作用是将多个打包结果中公共的部分抽取出来】*
webpack 如何做代码拆分
*我:递归 切片 chunk
1、按需加载拆分
2、拆分框架代码和业务代码
3、css代码拆分
*
webpack tree shaking 原理
摇树优化 是非常常见且极为有效的减少行冗余代码的策略。
使用静态模块声明风格意味着构建工具可以确定代码各部分之间的依赖关系。
更重要的是,
摇树优化还能确定代码中的哪些内容是完全不需要的。
在执行摇树优化时,导出未引用的工具函数、变量会被完全排除在打包文件之外。
静态分析也意味着构建工具可以确定未使用的依赖,同样也会排除掉。
通过摇树优化,最终打包得到的文件可以瘦身很多
webpack 动态导入原理\
webpack 热更新原理
*zhuanlan.zhihu.com/p/222582852
面试的时候说:
大概流程是我们用webpack-dev-server启动一个服务之后,浏览器和服务端是通过websocket进行长连接,webpack内部实现的watch就会监听文件修改,只要有修改就webpack会重新打包编译到内存中,然后webpack-dev-server依赖中间件webpack-dev-middleware和webpack之间进行交互,每次热更新都会请求一个携带hash值的json文件和一个js,websocker传递的也是hash值,内部机制通过hash值检查进行热更新, 至于内部原理,因为水平限制,目前还看不懂。
webpack5 新特性
-
通过持久缓存提高构建性能.
-
使用更好的算法和默认值来改善长期缓存.
-
通过更好的树摇和代码生成来改善捆绑包大小.
-
清除处于怪异状态的内部结构,同时在 v4 中实现功能而不引入任何重大更改.
-
通过引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 v5 链接:www.jianshu.com/p/82cf34de4…
esm 和 commonjs 的区别
*它们有三个重大差异。
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJS 模块的
require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。*
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块
import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。
除了静态加载带来的各种好处,ES6 模块还有以下好处。
- 不再需要
UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。 - 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者
navigator对象的属性。 - 不再需要对象作为命名空间(比如
Math对象),未来这些功能可以通过模块提供。
另外,
export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。这一点与 CommonJS 规范完全不同。CommonJS 模块输出的是值的缓存,不存在动态更新注意,import命令具有提升效果,会提升到整个模块的头部,首先执行
ES2020提案 引入import()函数,支持动态加载模块。
上面代码中,import函数的参数specifier,指定所要加载的模块的位置。import命令能够接受什么参数,import()函数就能接受什么参数,两者区别主要是后者为动态加载。
import()返回一个 Promise 对象。下面是一个例子。
const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
上面代码中,
<script>标签打开defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。 defer与async的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
TS 的 type 和 interface 的区别
zhuanlan.zhihu.com/p/383045717
TS 怎么做枚举\
www.jianshu.com/p/9779d392c… www.cnblogs.com/zzalmo/p/11…
TS 泛型
泛型可以理解为宽泛的类型,通常用于类和函数
www.jianshu.com/p/db084bda6…
canvas 绘制流程,canvas 里的图片跨域怎么处理
自己认为:先拿到dom,调用getContext获得绘图上下文,调用内置方法确定颜色坐标。stroke
绘制图形drawImage(dom,坐标,大小)dom可以是img也可以是另一个canvas
跨域:1.服务端Access-Control-Allow-Origin
2.要给对应的图片添加 crossOrigin 属性
var img = new Image();
img.crossOrigin = "Anonymous" ;
img.onload...
项目经历:babel 插件的实现\
编程题:实现一个深拷贝
递归
CSS 预处理器对比
变量声明sass:$ less:@
样式复用 less:.类名函数调用 声明正常 sass:声明前加 @mixin 类名 使用:@include 类名函数调用 循环不同。。。
www.cnblogs.com/dream111/p/…
CSS 定位有哪些取值
static默认 fixed absolute relative
原型与原型链,函数怎么实现继承
我:每个构造函数都有一个__proto__指针指向原型prototype,原型的constructor指针指向原型的构造函数。函数__proto__指向的原型的prototype指向Object的__proto__,对象原型的__proto__指向null。函数通过原型和构造函数实现继承
this的指向,call、apply的区别
new 实例化的this指向实例,全局作用域指向window,大部分都指向window,丢失指向window
bind修改this指向返回新函数。call apply修改this并立即调用 call参数是单个展开的(a,b,c,...) apply参数是数组arr
Vue 3.0 和 2.0 区别
*我常接触react:1.数据劫持和监听从Object.defineproperty 中的getter 和 setter 重写成 Proxy 提高性能 确定
自定义组件 maybe
*
Vue.$nextTick 作用
字面意思是下一步类似node中progress.nextTick maybe 用来流程控制的。异步代码同步化?
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
Vue 和 React 的 diff 有什么区别
*vue和react的diff算法,都是忽略跨级比较,只做同级比较。vue diff时调动patch函数,参数是vnode和oldVnode,分别代表新旧节点。
- vue比对节点,当节点元素类型相同,但是className不同,认为是不同类型元素,删除重建,而react会认为是同类型节点,只是修改节点属性
- vue的列表比对,采用从两端到中间的比对方式,而react则采用从左到右依次比对的方式。当一个集合,只是把最后一个节点移动到了第一个,react会把前面的节点依次移动,而vue只会把最后一个节点移动到第一个。总体上,vue的对比方式更高效。
diff算法遍历原理
- React 首位是除删除外是固定不动的,然后依次遍历对比;
- Vue 的compile 阶段的
optimize标记了static 点,可以减少 differ 次数,而且是采用双向遍历方法;
diff算法跟新DOM逻辑
- Vue基于snabbdom库,它有较好的速度以及模块机制。Vue Diff使用双向链表,边对比,边更新DOM。
- React主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。
proxy 拦截器的用法\
var obj = new Proxy({}, {
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
});
DNS 解析流程
我:Domain Name System浏览器发出请求时,先向dns服务询问域名对应个的ip地址与端口,在知道ip地址和端口之后再向相应的服务发出请求【缺少读缓存、读本地host】
关于dns域名解析的大致过程很多人都知道,但有些细枝末节的东西容易遗忘,今天有空整理一下,作为以后复习用,如有不对的地方,还望指正。解析大致过程如图(不喜欢看图的可以直接跳过):
当一个用户在地址栏输入www.taobao.com时,DNS解析有大致十个过程,如下:
-
浏览器先检查自身缓存中有没有被解析过的这个域名对应的ip地址,如果有,解析结束。同时域名被缓存的时间也可通过TTL属性来设置。
-
如果浏览器缓存中没有(专业点叫还没命中),浏览器会检查操作系统缓存中有没有对应的已解析过的结果。而操作系统也有一个域名解析的过程。在windows中可通过c盘里一个叫hosts的文件来设置,如果你在这里指定了一个域名对应的ip地址,那浏览器会首先使用这个ip地址。
但是这种操作系统级别的域名解析规程也被很多黑客利用,通过修改你的hosts文件里的内容把特定的域名解析到他指定的ip地址上,造成所谓的域名劫持。所以在windows7中将hosts文件设置成了readonly,防止被恶意篡改。
-
如果至此还没有命中域名,才会真正的请求本地域名服务器(LDNS)来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远,并且这台服务器的性能都很好,一般都会缓存域名解析结果,大约80%的域名解析到这里就完成了。
-
如果LDNS仍然没有命中,就直接跳到Root Server 域名服务器请求解析
-
根域名服务器返回给LDNS一个所查询域的主域名服务器(gTLD Server,国际顶尖域名服务器,如.com .cn .org等)地址
-
此时LDNS再发送请求给上一步返回的gTLD
-
接受请求的gTLD查找并返回这个域名对应的Name Server的地址,这个Name Server就是网站注册的域名服务器
-
Name Server根据映射关系表找到目标ip,返回给LDNS
-
LDNS缓存这个域名和对应的ip
-
LDNS把解析的结果返回给用户,用户根据TTL值缓存到本地系统缓存中,域名解析过程至此结束
原文链接:blog.csdn.net/m0_37812513…
事件循环
我:主线程在代码运行时,将代码分为同步代码和异步代码,碰到同步代码推入函数执行栈(先进后出),异步代码挂起等待,当执行栈执行完毕清空后,"事件循环"开始工作,检测任务队列是否有任务,任务队列的任务来源就是异步任务,在等待时间结束后会被放入任务队列。"事件循环"按任务进入顺序(先进先出)将任务拿到执行栈执行。如果执行栈执行过程中,无论是同步还是异步,过程中产生微任务,会先将该轮产生的微任务放入微任务队列,待本轮执行完毕后先依次执行微任务队列中的微任务。
闭包和内存泄漏
我:闭包:函数中返回函数,并且存在函数所在作用域中的引用,导致浏览器垃圾回收机制不进行回收。这样的变量会内存不会消失。过多会造成内存泄漏
最有亮点的一个项目
进程通信的几种方式 进程间通信主要包括管道, 系统IPC(包括消息队列,信号量,共享存储), SOCKET.
TCP/IP 如何保证传输稳定性
可靠性:三次握手建立连接
稳定性:切片+每一片的标识符用来组装
网络分层每层之间通信,不会因为某一层的变动影响其他层
*保证稳定性的机制有:
1.校验和(authentication sum) 就是说在数据传输的过程中 将发送的数据段映射为一个整数,然后加起来。发送方在发送数据之间计算校验和,然后接收方对收到的数据重新计算,与发送方进行对比。
2.TCP传输时将每个字节的数据都赋予了序列号(sequence number),每次发送端发送数据,接收方会回一个ack报文,报文里面会带有确认序列号。然后发送方就知道哪些数据已经被接收,下次数据从哪里开始发送。如果有丢包,就重发。
3. 而且针对丢包,TCP还有一种机制,叫超时重传(resend the package if timeout),就是说发送方发完包没有得到回应,过段时间就会自动重新发送。
4.当网络阻塞的时候,传输的稳定性就很差,所以TCP有拥塞控制(flow control),就是用滑动窗口来来动态的控制每次发送的数据量。窗口的大小怎么设置?窗口的大小就是在无需等待确认包的情况下,发送端还能发送的最大数据量。
顺口溜: 校验和,序列号,超时重传拥塞控 blog.csdn.net/weixin_4433…*
对称加密和非对称加密的使用场景 *在了解使用场景之前,先分析一下非对称加密。 公钥私钥本质上是一样的(也就是说两者可以互换),之所以这么区分,就是因为一个公开了,另一个没公开,公开了就意味着有风险。 如果我们先用私钥加密一个信息,然后把信息发出去,让别人用我们之前公开或发送的公钥解密来获取信息,这是一种使用方法。相应的场景有签名(服务端加签、客户端解签验证)。像我们平时通过xshell直连服务器,一般是通过ssh协议,xshell生成一对公钥私钥,把私钥放在本地C:\Users\用户名.ssh目录下并导入shell,把公钥发送给服务器管理员,放在服务器中。这样我们连接服务器的时候,使用自己私钥加密,然后发给服务器使其用公钥解密,达到一个签名的效果。再比如git中也是支持https和ssh两种协议。 相反的一个场景就是加解密了,比如常见的https中,服务端先给客户端发送一个公钥,客户端通过公钥解密一些信息(比如客户端生成的会话秘钥),发送给服务端,服务端通过自己的私钥解密,达到信息安全传输的目的。 原文链接:blog.csdn.net/qq_31363843… *
浏览器帧卡顿检测 requestAnimationFrame zhuanlan.zhihu.com/p/103689254
Vue 和 React的设计理念 *www.cnblogs.com/zhulimin/p/… juejin.cn/post/684490… baijiahao.baidu.com/s?id=171592… *
性能指标FP、FCP和FMP分别跟哪些因素有关 zhuanlan.zhihu.com/p/98880815
FP(全称“First Paint”,翻译为“首次绘制”
是时间线上的第一个“时间点”,它代表浏览器第一次向屏幕传输像素的时间,也就是页面在屏幕上首次发生视觉变化的时间。*
注意:FP不包含默认背景绘制,但包含非默认的背景绘制。
FCP(全称“First Contentful Paint”,翻译为“首次内容绘制”)### ,顾名思义,它代表浏览器第一次向屏幕绘制 “内容” 。
注意:只有首次绘制文本、图片(包含背景图)、非白色的
canvas或SVG时才被算作FCP。
FP与FCP这两个指标之间的主要区别是:FP是当浏览器开始绘制内容到屏幕上的时候,只要在视觉上开始发生变化,无论是什么内容触发的视觉变化,在这一刻,这个时间点,叫做FP。
相比之下,FCP指的是浏览器首次绘制来自DOM的内容。例如:文本,图片,SVG,canvas元素等,这个时间点叫FCP。
FP和FCP可能是相同的时间,也可能是先FP后FCP。
FMP(全称“First Meaningful Paint”,翻译为“首次有效绘制”)### 表示页面的“主要内容”开始出现在屏幕上的时间点。它是我们测量用户加载体验的主要指标。
FMP本质上是通过一个算法来猜测某个时间点可能是FMP,所以有时候不准。
图3给出了FP、FCP、FMP之间的比较。
低代码平台的技术原理
业界其他低代码平台实现方式,对比差异 nginx怎么做反向代理与负载均衡 编程题:设计和实现一个 LRU (最近最少使用) 缓存机制,满足:1.获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。2.写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。
JS 有哪些数据类型 简单类型、复杂类型 简单类型(基本类型):String Number Bollean Symbol Undefined Null 复杂:Object
JS 数据类型识别的方式,有什么缺点 *typeOf araay object 都是 object instacne of *
原型和原型链,函数怎么实现继承
new 发生了什么 内存中开辟一块新的空间做存储,返回实例对象,this指向当前实例,原型指向构造函数的原型
symbol 类型的用法 独一无二的标识符,a = Symbol('a'),Symbol内可穿入对象,每个Symbol都是独一无二的,
script 标签里分别设置 defer 和 async, 它们的执行顺序是怎么样的 都是延迟加载,区别是defer全部执行完成后执行,async是等js加载完成时候立刻停止其他事情执行
React router 的两种模式模式,怎么动态获取路由上的 id hash 和 history 。params.id
redux 中间件的实现原理 高阶函数
React 的 purecomponent 和 component 的区别
React.Component is the base class for React components when they are defined using ES6 classes:
React.PureComponent is similar to React.Component. The difference between them is that React.Component doesn’t implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison.
If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.
Note React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data. Furthermore, React.PureComponent’s shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also “pure”.
中文意思:React.PureComponent 与 React.Component 基本相同。 区别:Component 没有直接实现 shouldComponentUpdate 这个方法;但是 PureComponent通过浅层的Porps 和 state 的对比,内部实现了这个生命周期函数。 如果你的组件 render 函数渲染时具有相同的 props 和 state,那么可以使用 PureComponent 来提高性能。 注意:PureComponent仅仅实现对象的浅对比。如果对象中包含复杂的数据结构,会产生较大的区别。除非你的state 和 props 是简单的,或者当你的深层数据结构变化时使用 forceUpdate,或者使用 immutable 对象来快速比较嵌套(复杂)的数据。此外:PureComponent会跳过整个组件子树的props更新,要确保全部的子组件也是 pure 的形式。blog.csdn.net/weixin_4169…
generator 函数的用法
function *acc(){
yield xxx
yield xxxx
yield xxxxx
}
let a = acc();
a.next();
a.next();
// 返回{ done : 状态,value : yeild的值 }
React diff 节点对比的过程
Vite 打包工具的使用
箭头函数和普通函数区别
- 语法更加简洁、清晰
- 箭头函数不会创建自己的
this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。 - 箭头函数继承而来的this指向永远不变
- 箭头函数不能作为构造函数使用
- .call()/.apply()/.bind()无法改变箭头函数中this的指向
- 箭头函数没有原型prototype
- 箭头函数没有自己的arguments ,是上层作用域的
- 箭头函数不能用作Generator函数,不能使用yeild关键字
什么是执行上下文 函数执行时候动态创建的活动作用域[[SCOPe]] 作用玉链chain 最终globle全局window
堆内存和栈内存,数组存储在堆内存还是栈内存 指针在栈,值在堆
HTTP2.0 相较于 HTTP1.0 的改进 juejin.cn/post/684490…
isNaN和number.isNaN区别
isNaN会通过Number方法,试图将字符串"测试"转换成Number类型,但转换失败了,因为 Number('测试') 的结果为NaN ,所以最后返回true。 而Number.isNaN方法,只是严格的判断传入的参数是否全等于NaN( '测试' === NaN) ,字符串当然不全等于NaN啦,所以输出false。
闭包和内存泄漏 setState 是同步还是异步的 HTTP 与 HTTPS 的区别 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由进行,提供了身份验证与加密通讯方法,现在它被广泛用于网上安全敏感的通讯,例如交易支付方面。
- https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
- http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
- http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
React Hooks 的 useState 为什么不能放到条件语句
这是因为React通过单链表来管理Hooks。update 阶段,每次调用 useState,链表就会执行 next 向后移动一步。如果将 useState 写在条件判断中,假设条件判断不成立,没有执行里面的 useState 方法,会导致接下来所有的 useState 的取值出现偏移,从而导致异常发生。 (以
useState为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在memoizeState属性)
zhuanlan.zhihu.com/p/304213203
解释下浏览器的同源策略 同协议+同域名+同端口 是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。 它能帮助阻隔恶意文档,减少可能被攻击的媒介。
HTTP2.0 和 HTTP1.0 的区别,HTTP2.0 有什么缺点
- 果有丢包请求会等待重传,阻塞后面的数据,有可能不如http1.1的多个TCP连接TCP 以及TCP+TLS 建立连接的延时
- TCP 的队头阻塞并没有彻底解决TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认
- 多路复用导致服务器压力上升,多路复用没有限制同时请求数。
闭包及闭包的使用场景
实现一个侧边栏组件思路
浏览器缓存机制
简单来说,浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中。 缓存会根据进来的请求保存输出内容的副本。 当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。
重排与重绘,怎么减少重排
- 重绘:某些元素的外观被改变,例如:元素的填充颜色
- 重排:重新生成布局,重新排列元素。 减少:
减少重排范围
减少重排次数
DOM 事件机制,不会冒泡的事件 cookie 和 session 的区别
大小、时间长短
sql 相关操作,增删查改
blog.csdn.net/ljianhui/ar…
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)
DELETE FROM Person WHERE LastName = 'Wilson'
删除所有行,DELETE FROM table_name或DELETE * FROM table_name(注意,并不删除表);
UPDATE Person SET FirstName = 'Fred' WHERE LastName = 'Wilson'
UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson'
SELECT * FROM Persons WHERE City='Beijing'
SELECT SUM(OrderPrice) AS OrderTotal FROM Orders;as表示生成的数据的列名是OrderTotal
SELECT COUNT(Customer) AS CustomerNilsen FROM Orders WHERE Customer='Carter'
SELECT Customer,OrderDate,SUM(OrderPrice) FROM Orders GROUP BY Customer,OrderDate
GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。通常与sum()、count()等函数一起用。
web 安全,xss、csrf 攻击特点及防御方式
*xss crosssite script 跨站脚本可攻击 动态插入可执行的脚本 -> 对可输入的地方进行过滤 csrf Cross-Site Request Forgery 跨站请求伪造
-
阻止不明外域的访问
- 同源检测
- Samesite Cookie
-
提交时要求附加本域才能获取的信息
- CSRF Token
- 双重Cookie验证 tech.meituan.com/2018/10/11/…
Map怎么转对象 ES2019 Object.fromEntries(map) new Map(Object.entries(obj))
reduce和reduceRight 两个方法都会迭代数组的所有项,并在此基础上构建一个最终的返回值。回调四个参数 (prev,cur,index,array) 上一次的归并值,当前项,当前项的索引和数组本身。reduce函数接收两个参数一个是回调函数,一个是可选的以之为归并起点的起始值 reduce 是从第一项到最后一项。reduceRight是从最后一项往前
compose和管道函数 compose函数指的是对要嵌套执行的函数进行平铺,嵌套执行指的是一个函数的返回结果作为另一个函数的执行参数。核心思想是专注于函数执行过程,隔离数据的影响。
let compose = () => {
const args = [].concat(arguments);
return (x) => {
return args.reduce( (pre,cur)=> cur(pre),x )
}
}
let compose = (...args) => (x) => args.reduce( (pre,cur)=> pre(cur) , x )
// compose函数是从右向左去实现的数据执行流,而从左向右的数据执行流就是pipe函数了(通一个第二个你自然也就会了)
// 需要说明的现在前端工具webpack 中loader 的执行顺序就是compose方法实现的。
axios取消
const source = axios.CancelToken;
// 返回 { token,cancel }
// token用于表示某个请求,是一个Promise类型
// cancel是一个方法 当被调用时 则取消token注入那个请求
axios.get('xx/xx',{ cacelToken:source.token }) // 将token注入
.catch( (thrown)=> if(axios.isCancel(thrown)) console.log('REQUEST CANCEL',thrown.message) )
source.cancel('去取消');
两个字组件共用一个父组件传来的值,改变两个都会更新。怎样使得B只在那个值等于1的时候更新?
react-rxjs redux-observable
redux-observable 只有一个数据源,在 dispatch 的过程触发事件,进入 action 逻辑。其实每个 action 都源自对同一个数据源的订阅,通过 action.type 的筛选来确保执行了正确的 action。
所以每次 dispatch,包括 mapTo 也是 dispatch,都会触发数据源的事件派发,然后所有 Action 因为订阅了这个数据源,所以都会执行,最后被 .filter 逻辑拦截后,执行到正确的 Action。整个 Action 间调用的链路打个比方,就像我们使用微信一样,当触发任何消息,都会将其送到后台服务器,服务器给所有客户端发消息(假设系统设计的有问题,没有在服务端做 filter。。),每个客户端根据用户名做一个筛选,如果不是发给自己的消息,就过滤掉。然后,任何人与人之间的消息发送,都会走一遍这个流程。
websocket步骤,参数类型 1.实例话const socket = new Websocket('xxx.php'); // 打开 2.socket.send("hello world"); socket.send(Uint8Array.from([1,2,3]).buffer); socket.send(new Blob(['f','o','o'])) 3.socket.onmessage(); 4.socket.close();
-
文本字符串。字符串将以 UTF-8 格式添加到缓冲区,并且
bufferedAmount将加上该字符串以 UTF-8 格式编码时的字节数的值。 -
您可以使用一有类型的数组对象发送底层二进制数据;其二进制数据内存将被缓存于缓冲区,
bufferedAmount将加上所需字节数的值。 -
Blob类型将队列 blob 中的原始数据以二进制中传输。bufferedAmount将加上原始数据的字节数的值。 -
您可以以二进制帧的形式发送任何 JavaScript 类数组对象 ;其二进制数据内容将被队列于缓冲区中。值
bufferedAmount将加上必要字节数的值。WebSocket.binaryType返回websocket连接所传输二进制数据的类型。 一条DOMString: -
"blob"如果传输的是
Blob类型的数据。 -
"arraybuffer"如果传输的是
ArrayBuffer类型的数据。
antd FormItem中使用自定义组件需要注意什么
- 提供受控属性
value或其它与valuePropName的值同名的属性。 - 提供
onChange事件或trigger的值同名的事件。
自定义组件从props解构出 value 和 onChange 内部 return 的 组件value先读value.xxx 没有则再读内部的state 组件的onChange 最后调用顶层传下来的 onChange 并传参数{key :value}
React。createElement 入参 React.createElement(type,[props],[...children])
child1 = React.createElement('li',null,'one'); child2 = React.createElement('li',null,'two'); contentt = React.createElement('ul',{className:"test-list"},child1,child2) 或者 content t= React.createElement('ul',{className:"test-list"},[child1,child2] )
父useRef 子使用 父:const ff = useRef();
Child = React.forwardRef((props,reff)=> )// Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。
为什么要转发
第二个参数 ref 只在使用 React.forwardRef 定义组件时存在。常规函数和 class 组件不接收 ref 参数,且 props 中也不存在 ref。
Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。
子组件转发给父组件
useImperativeHandle
useImperativeHandle(ref, createHandle, [deps])
useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
在本例中,渲染 <FancyInput ref={inputRef} /> 的父组件可以调用 inputRef.current.focus()。
知识面窄,读文档
Vue router有哪些钩子函数 Vue module是干什么用的 Vue router 路由守卫有哪些 Vue router 怎么实现 Class 装饰器 Proxy
Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,所以属于一种“元编程”,即对编程语言进行编程。
Proxy可以理解成在目标对象钱假设一个“拦截”层,外界对该对象的访问都必须先通过这层拦截,因此提供了一种机制可以对外界的访问进行过滤和改写。Prxoy这个词的原意是代理,用在这里表示由他来“代理”某些操作,可以译作代理器。
var obj = new Proxy( {},{
get : function(target , propname, ,receiver){
console.log(`get ${propname}`);
return Reflect.get(target , propname,receiver)
}
set : function (target,propname,value,receiver){
console.log(`set ${propname}`);
return Reflect.set(target , propname,value,receiver)
}
} )
get(target , propkey, receiver)
set(target , propkey,value , receiver)
has(target , propkey)
deleteProperty(target,key)
ownKeys(target) : 拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy),Obejct.keys(proxy) ,返回一个数组。该方法返回目标对象所有自身属性的属性名,而Object.keys()的返回结果仅仅包括目标对象自身的课美剧属性
getOwnPropertyDescriptor
defineProperty
getPrototypeOf
setprototypeOf
isExtensible
apply(target,object,args)
construct(target,args)
async await怎么写并发
var fs=require('fs');
var read=function (path) {
return new Promise((resolve,reject)=>{
fs.readFile(path,(err,data)=>{
if(err){
reject(err)
}else{
resolve(data)
}
})
})
}
//继发读取
async function ReadTwo(){
var f1=await read('./a.txt');
var f2=await read('./b.txt');
}
async function readTwo{ var p=Promise.all([read('./a.txt'),read('./b.txt')]); var [f1,f2]=await p }
微应用原理 ,为什么不用iframe
IFrame 问题
概况下,技术问题大致归纳下几类:
- url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
- UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..
- 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
- 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
具体的业务场景:
- 运营平台页面的 modal 弹窗,全部都无法居中显示
- 运营平台页面无法同步 url 状态,iframe 内部发生页面跳转之后,浏览器的前进/后退按钮状态不对。
- 运营平台用户登录超时时,无法自动跳转到登录页面。为了解决这个问题,用 postMessage 实现了一套非常复杂的流程,容易出错而且性能不高
- 运营平台如果想复用小程序研发平台的部分能力(比如工单审批),技术方案非常复杂。需要在 postMessage 基础上进行多层封装,设计到了轮询、超时等各种异常边界问题
样式隔离: 样式隔离的问题,其实刚才讲了。可以有两种方式:一种是使用一些工程化的手段,不管是约定前缀,或者说使用 css module 做一些改造都可以避免主子应用之间的样式冲突。你也可以尝试去开启严格的样式隔离,使用Shadow DOM 的方式来让子应用样式真正地做隔离,但是这个时候你的子应用可能会遇到一些新的问题需要你解决。
原理:核心的技术是 systemjs 和Single-Spa blog.csdn.net/weixin_4352…
类和函数继承的区别,super做了什么 www.cnblogs.com/constantinc… blog.csdn.net/qq_41916378…
VUE通信