首页IT科技前端面试一般问些什么(前端面试常问的题目(持续更新中))

前端面试一般问些什么(前端面试常问的题目(持续更新中))

时间2025-04-28 14:32:08分类IT科技浏览3252
导读:1、闭包问题...

1          、闭包问题

什么是闭包?答:“闭包就是能够读取其他函数内部变量的函数

造成闭包的原因?答:

解决方法?答:可以使用let                、立即执行函数

闭包可以实现什么?可以访问局部变量      、可以保护变量不受污染

2        、ajax               、axios 前后端通信的过程(原生的ajax怎么写)

原生ajax请求步骤get:

1.创建核心的对象(new xhrhttprequest对象)

2.编写回调函数(判断是否请求成功 状态码等于4或者等于200)

3.调用open方法 设置请求方式和请求路径

4.调用send方法 发送

post:要多设置一个请求头setrequestheader(在发送的前面)

3         、跨域问题(具体实现)

答:跨域解决方式:

1.jsonp(script这个标签本来就有跨域的能力          ,然后将ajax中datatype中类型改为jsonp)缺点只支持get

2.利用cors设置头 允许跨域(头有哪些)优点:支持get和post两种

使用普通的XMLHttpRequest发起请求和获得数据                ,比起JSONP有更好的错误处理

3.利用proxy代理(具体实现不管是否跨域      ,在自己服务器上中转一次        ,让它允许跨域               ,类似于一个中转站的意思)

4      、浏览器的渲染流程

这个问题应该就是输入url到页面呈现问题的变种         ,只不过此时的侧重点是获取完数据之后进行的渲染流程          。

根据李兵老师的浏览器工作原理一节做如下回答:

第一步      ,HTML转换成DOM

第二步               ,CSS转换成浏览器可理解的styleSheets            ,然后计算DOM节点的样式

第三步   ,创建布居树               ,计算元素的布局信息

第四步               ,对布居树进行分层,构建分层树

第五步            ,为每个图层生产绘制列表                 ,并将其提交到合成线程

第六步   ,合成线程将图层转化为图块          ,进而将图块转化成位图

第七步                ,合成线程发送绘制命令给浏览器

第八步      ,浏览器根据绘制命令生成页面        ,并显示到显示器上                。

 

5               、deffer和async的区别

浏览器脚本               ,在普通的情况下         ,是会依次执行      。但是我们可以用deffer和async关键字来让脚本异步执行        。

但是      ,deffer是按照加载顺序执行DOMContentLoaded之前执行               ,但是async则是脚本加载完毕之后立即执行(不考虑依赖以及DOM的加载状态)            ,一般来说   ,deffer要比async好一点               。

6            、map和forEach的区别

forEach返回undefined               ,map会返回新的数组         。

forEach没办法中止循环               ,但是map可以通过返回false或者出错来中止      。

7   、call               、apply以及bind的区别               。

三者都是改变this执行,不同的是            ,call和apply是直接生成了函数调用                 ,而bind则是返回了一个函数   ,你需要再次执行才会达到相同的效果            。

call和apply又是因为参数的传递方式不一样          ,apply传递的是数组                ,call传递的单个参数的陈列   。

bind则是以函数调用参数的方式传递参数               。

8               、事件循环               。

JavaScript是单线程执行模型      ,执行的时候将会区分为主线程和任务队列。主线程执行完毕        ,会从任务队列中读取新的任务放入主线程进行执行               ,这个读取过程是循环读取         ,所以也叫事件循环            。

任务队列分为宏任务和微任务      ,同层次               ,先执行微任务            ,再执行宏任务                 。

微任务:promise.then()、process.nextTick()

宏任务:setTimeOut()            、setInterval()

9                 、get和post请求区别

GET在浏览器回退时是无害的   ,而POST会再次提交请求   。

GET产生的URL地址可以被Bookmark               ,而POST不可以          。

GET请求会被浏览器主动cache               ,而POST不会,除非手动设置                。

GET请求只能进行url编码            ,而POST支持多种编码方式      。

GET请求参数会被完整保留在浏览器历史记录里                 ,而POST中的参数不会被保留        。

GET请求在URL中传送的参数是有长度限制的   ,而POST么有               。

对参数的数据类型          ,GET只接受ASCII字符                ,而POST没有限制         。

GET比POST更不安全      ,因为参数直接暴露在URL上        ,所以不能用来传递敏感信息      。

GET参数通过URL传递               ,POST放在Request body中               。

GET产生一个TCP数据包;POST产生两个TCP数据包            。

GET与POST都有自己的语义         ,不能随便混用   。

10   、双向绑定原理

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的

我们已经知道实现数据的双向绑定      ,首先要对数据进行劫持监听               ,所以我们需要设置一个监听器Observer            ,用来监听所有属性               。如果属性发上变化了   ,就需要告诉订阅者Watcher看是否需要更新               。因为订阅者是有很多个               ,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者               ,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile            ,对每个节点元素进行扫描和解析                 ,将相关指令(如v-model   ,v-on)对应初始化成一个订阅者Watcher          ,并替换模板数据或者绑定相应的函数                ,此时当订阅者Watcher接收到相应属性的变化      ,就会执行对应的更新函数        ,从而更新视图            。

11          、Async和Await原理

async                、await从字面上理解               ,async就是异步的意思         ,await就是等待的意思      ,而两者的用法上也是这样的               ,async用于申明一个function是异步的            ,而await用于等待一个异步方法执行完成

过程就是:

1   ,async就是一个async函数               ,而await只能在这个函数中使用

2               ,await表示这里等待await后面的操作执行完毕,再执行下一句代码

3            ,await后面紧跟的最好是一个定时操作或者一个异步操作

async和await的优点

1                 ,解决了回调地狱的问题

2   ,支持并发执行

3          ,可以添加返回值 return xxx

4                ,可以在代码中添加try/catch捕获错误

12      、webpack工作原理

1        、核心概念

(1)entry:一个可执行模块或者库的入口                 。

(2)chunk:多个文件组成一个代码块   。可以将可执行的模块和他所依赖的模块组合成一个chunk      ,这是打包          。

(3)loader:文件转换器                。例如把es6转为es5        ,scss转为css等

(4)plugin:扩展webpack功能的插件      。在webpack构建的生命周期节点上加入扩展hook               ,添加功能

2               、webpack构建流程(原理)

从启动构建到输出结果一系列过程:

(1)初始化参数:解析webpack配置参数         ,合并shell传入和webpack.config.js文件配置的参数      ,形成最后的配置结果        。

(2)开始编译:上一步得到的参数初始化compiler对象               ,注册所有配置的插件            ,插件监听webpack构建生命周期的事件节点   ,做出相应的反应               ,执行对象的 run 方法开始执行编译               。

(3)确定入口:从配置的entry入口               ,开始解析文件构建AST语法树,找出依赖            ,递归下去         。

(4)编译模块:递归中根据文件类型和loader配置                 ,调用所有配置的loader对文件进行转换   ,再找出该模块依赖的模块          ,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理      。

(5)完成模块编译并输出:递归完事后                ,得到每个文件结果      ,包含每个模块以及他们之间的依赖关系        ,根据entry配置生成代码块chunk               。

(6)输出完成:输出所有的chunk到文件系统            。

注意:在构建生命周期中有一系列插件在做合适的时机做合适事情               ,比如UglifyPlugin会在loader转换递归完对结果使用UglifyJs压缩覆盖之前的结果

13         、webpack的loader和plugin区别

【Loader】:用于对模块源码的转换         ,loader描述了webpack如何处理非javascript模块      ,并且在buld中引入这些依赖   。loader可以将文件从不同的语言(如TypeScript)转换为JavaScript               ,或者将内联图像转换为data URL               。比如说:CSS-Loader            ,Style-Loader等               。

loader的使用很简单:

在webpack.config.js中指定loader。module.rules可以指定多个loader   ,对项目中的各个loader有个全局概览            。

loader是运行在NodeJS中               ,可以用options对象进行配置                 。plugin可以为loader带来更多特性   。loader可以进行压缩               ,打包,语言翻译等等          。

loader从模板路径解析            ,npm install node_modules                。也可以自定义loader                 ,命名XXX-loader      。

语言类的处理器loader:CoffeeScript   ,TypeScript          ,ESNext(Bable),Sass,Less,Stylus        。任何开发技术栈都可以使用webpack               。

【Plugin】:目的在于解决loader无法实现的其他事                ,从打包优化和压缩      ,到重新定义环境变量        ,功能强大到可以用来处理各种各样的任务         。webpack提供了很多开箱即用的插件:CommonChunkPlugin主要用于提取第三方库和公共模块               ,避免首屏加载的bundle文件         ,或者按需加载的bundle文件体积过大      ,导致加载时间过长               ,是一把优化的利器      。而在多页面应用中            ,更是能够为每个页面间的应用程序共享代码创建bundle               。

14      、promise 与 async await

async/await是写异步代码的新方式   ,以前的方法有回调函数和Promise            。

  async/await是基于Promise实现的               ,它不能用于普通的回调函数   。

  async/await与Promise一样               ,是非阻塞的               。

  async/await使得异步代码看起来像同步代码,这正是它的魔力所在

函数前面多了一个aync关键字               。await关键字只能用在aync定义的函数内。async函数会隐式地返回一个promise            ,该promise的reosolve值就是函数return的值            。(示例中reosolve值就是字符串          ”done                ”)

为什么Async/Await更好?

1)使用async函数可以让代码简洁很多                 ,不需要像Promise一样需要些then   ,不需要写匿名函数处理Promise的resolve值          ,也不需要定义多余的data变量                ,还避免了嵌套代码                 。

2) 错误处理:

    Async/Await 让 try/catch 可以同时处理同步和异步错误   。在下面的promise示例中      ,try/catch 不能处理 JSON.parse 的错误        ,因为它在Promise中          。我们需要使用 .catch               ,这样错误处理代码非常冗余                。并且         ,在我们的实际生产代码会更加复杂

​ 3) 使用async/await的话      ,代码会变得异常简单和直观      。

4)错误栈

    如果 Promise 连续调用               ,对于错误的处理是很麻烦的        。你无法知道错误出在哪里               。

async/await中的错误栈会指向错误所在的函数         。在开发环境中            ,这一点优势并不大      。但是   ,当你分析生产环境的错误日志时               ,它将非常有用               。这时               ,知道错误发生在makeRequest比知道错误发生在then链中要好            。

5)调试

    async/await能够使得代码调试更简单   。2个理由使得调试Promise变得非常痛苦:

《1》不能在返回表达式的箭头函数中设置断点

   《2》如果你在.then代码块中设置断点,使用Step Over快捷键            ,调试器不会跳到下一个.then                 ,因为它只会跳过异步代码               。

使用await/async时   ,你不再需要那么多箭头函数          ,这样你就可以像调试同步代码一样跳过await语句               。

15               、重绘和汇流有什么区别

什么是回流                ,什么是重绘      ,有什么区别?

html 加载时发生了什么:

在页面加载时        ,浏览器把获取到的HTML代码解析成1个DOM树               ,DOM树里包含了所有HTML标签         ,包括display:none隐藏      ,还有用JS动态添加的元素等。

浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体

DOM Tree 和样式结构体组合后构建render tree, render tree类似于DOM tree               ,但区别很大            ,因为render tree能识别样式   ,render tree中每个NODE都有自己的style               ,而且render tree不包含隐藏的节点(比如display:none的节点               ,还有head节点),因为这些节点不会用于呈现            ,而且不会影响呈现的                 ,所以就不会包含到 render tree中            。我自己简单的理解就是DOM Tree和我们写的CSS结合在一起之后   ,渲染出了render tree                 。

什么是回流:

当render tree中的一部分(或全部)因为元素的规模尺寸          ,布局                ,隐藏等改变而需要重新构建   。这就称为回流(reflow)          。每个页面至少需要一次回流      ,就是在页面第一次加载的时候        ,这时候是一定会发生回流的               ,因为要构建render tree                。在回流的时候         ,浏览器会使渲染树中受到影响的部分失效      ,并重新构造这部分渲染树               ,完成回流后            ,浏览器会重新绘制受影响的部分到屏幕中   ,该过程成为重绘      。

什么是重绘:

当render tree中的一些元素需要更新属性               ,而这些属性只是影响元素的外观               ,风格,而不会影响布局的            ,比如background-color        。则就叫称为重绘               。

区别:

他们的区别很大:

回流必将引起重绘                 ,而重绘不一定会引起回流         。比如:只有颜色改变的时候就只会发生重绘而不会引起回流

当页面布局和几何属性改变时就需要回流

比如:添加或者删除可见的DOM元素   ,元素位置改变          ,元素尺寸改变——边距            、填充   、边框               、宽度和高度                ,内容改变

扩展:

浏览器的帮忙

所以我们能得知回流比重绘的代价要更高      ,回流的花销跟render tree有多少节点需要重新构建有关系

因为这些机制的存在        ,所以浏览器会帮助我们优化这些操作               ,浏览器会维护1个队列         ,把所有会引起回流               、重绘的操作放入这个队列      ,等队列中的操作到了一定的数量或者到了一定的时间间隔               ,浏览器就会flush队列            ,进行一个批处理      。这样就会让多次的回流、重绘变成一次回流重绘               。

自己的优化

靠浏览器不如靠自己   ,我们可以改变一些写法减少回流和重绘

比如改变样式的时候               ,不去改变他们每个的样式               ,而是直接改变className 就要用到cssText 但是要注意有一个问题,会把原有的cssText清掉            ,比如原来的style中有’display:none;’                 ,那么执行完上面的JS后   ,display就被删掉了            。

为了解决这个问题          ,可以采用cssText累加的方法                ,但是IE不支持累加      ,前面添一个分号可以解决   。

还有添加节点的时候比如要添加一个div里面有三个子元素p        ,如果添加div再在里面添加三次p               ,这样就触发很多次回流和重绘         ,我们可以用cloneNode(true or false) 来避免      ,一次把要添加的都克隆好再appened就好了               ,还有其他很多的方法就不依依说了

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
seo排名优化方式(seo技巧seo排名优化,seo排名优化是什么意思) centos6安装epel(CentOS系统镜像安装 EPEL 源方法和教程)