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

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

时间2025-08-03 04:24:48分类IT科技浏览4343
导读: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
浏览广告赚钱下载(浏览广告赚钱有哪些-浏览广告能赚钱?吉林女子加入传销后来连家人都不放过) 搜索网站怎么操作(网站搜索技巧)