1.async和defer的区别
defer和async是script标签的两个属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行。
作用
- defer:用于开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
- async:新增属性,用于异步下载脚本文件,下载完毕立即解释执行代码。
1.先来试个一句话解释仨,当浏览器碰到 script 脚本的时候:
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
然后从实用角度来说呢,首先把所有脚本都丢到 之前是最佳实践,因为对于旧浏览器来说这是唯一的优化选择,此法可保证非脚本的其他一切元素能够以最快的速度得到加载和解析。
接着,我们来看一张图:
蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。
此图告诉我们以下几个要点:
- defer 和 async 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
- 它俩的差别在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的
- 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
- async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行
- 仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics
2.forEach和map的区别
forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
3.路由权限实现原理
- 用户登录获取用户id或者token;
- 根据token或者用户id去获取用户对应的权限;
- 获取到用户权限后进行缓存,并存储到pinia中;
- 根据获取的用户权限生成对应的菜单;
- 根据编写好的route结合用户权限生成对应的router,并通过addRoute添加到路由实例中。
4.SPA与SSR区别
SPA单页应用程序 | SSR服务器端渲染 | |
优势 | 1.页面内容在客户端渲染 2. 只关注View层,与后台耦合度低,前后端分离 3.减轻后台渲染画面的压力 | 1.更好的SEO,搜索引擎工具可以直接查看完全渲染的画面 2.更快的内容到达时间 (time-to-content),用户能更快的看到完整渲染的画面 |
劣势 | 1.首屏加载缓慢 2.SEO(搜索引擎优化)不友好 | 1.更多的服务器端负载 2.涉及构建设置和部署的更多要求,需要用Node.js渲染 3.开发条件有限制,一些生命周期将失效 4.一些常用的浏览器API无法使用 |
5.GET/POST区别
6.前后端分离的理解
前端开发没有像后端开发那样实现工程化、模块化、可复用化的思想。所以就会出现前后端开发不协调、效率低、扯皮的问题,这很不利于项目开发。因此项目管理者就想办法来解决这种问题--需要分离的原因。这些与vue、react框架没有什么关系,它们充其量只是一种具体实现方式而已。从本质上来看,前后端分离并不是一个技术问题,而是一个工程化考量和项目管理的问题。
前后端分离核心思想是前端HTML页面通过AJAX调用后端的RESTFUL API接口并使用JSON数据进行交互。
7.[1,2,3].map(parseInt)
三、再来分析一下结果
['1','2','3'].map(parseInt)即
parseInt('1',0);radix 为 0,parseInt() 会根据十进制来解析,所以结果为 1;
parseInt('2',1);radix 为 1,超出区间范围,所以结果为 NaN;
parseInt('3',2);radix 为 2,用2进制来解析,应以 0 和 1 开头,所以结果为 NaN。
四、parseInt方法解析的运算过程
parseInt('101.55',10); //以十进制解析,运算过程:向上取整数(不做四舍五入,省略小数),结果为 101。
parseInt('101',2); //以二进制解析,运算过程:12的2次方+02的1次方+12的0次方=4+0+1=5,结果为 5。parseInt('101',8); //以八进制解析,运算过程:18的2次方+08的1次方+18的0次方=64+0+1=65,结果为 65。
parseInt('101',16); //以十六进制解析,运算过程:116的2次方+016的1次方+1*16的0次方=256+0+1=257,结果为 257。
8.闭包原理
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其他外层函数的作用域。
简单理解:闭包=内层函数+引用的外层函数变量。
function outer(){ const a = 1 function f(){ console.log(a) f() } outer()
而且闭包不一定需要return
外界能够使用闭包中的变量,却不能修改,因为闭包变量私有化。
优点:
1、可以从内部函数访问外部函数的作用域中的变量,且访问到的变量长期驻扎在内存中,可供之后使用。
2、避免变量污染全局。
3、把变量存到独立的作用域,作为私有成员存在。
9.什么是事件循环
1.js是单线程,防止代码阻塞,我们把代码(任务):同步和异步
2.同步代码给js引擎执行,异步代码交给宿主环境
3.同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
4.执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环。eventloop。
10.promise
Promise是JS中进行异步编程的新的解决方案
- promise 是一个构造函数
- Promise 的构造函数接收一个函数为参数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
为什么要用Promise
- 指定回调函数的方法更加灵活
- 支持链式调用 ,可以解决回调函数问题