当前位置: 首页 > Web前端 > HTML

前端高频面试题(附答案)

时间:2023-03-27 23:39:15 HTML

先说说HTTP3.0HTTP/3是基于UDP协议实现类似TCP的数据流复用、传输可靠性等功能。这组函数称为QUIC协议。流量控制、传输可靠性功能:QUIC在UDP的基础上增加了一层保证数据传输的可靠性。它提供数据包重传、拥塞控制和TCP中的一些其他功能。集成TLS加密功能:目前QUIC使用TLS1.3,减少了握手时花费的RTT次数。多路复用:同一个物理连接上可以有多个独立的逻辑数据流,实现了数据流的分离传输,解决了TCP的队头阻塞问题。快速握手:因为是基于UDP的,所以可以使用0~1个RTT建立连接。前端高级面试题详解箭头函数和普通函数的区别(1)箭头函数比普通函数更简洁。如果没有参数,就写一个空括号。如果只有一个参数,可以省略参数的括号。参数,以逗号分隔。如果函数体的返回值只有一句话,大括号可以省略。如果函数体不需要返回值,而且只有一句话,可以在这句语句前加一个void关键字。最常见的是调用函数:letfn=()=>voiddoesNotReturn();复制代码(2)箭头函数没有自己的this箭头函数不会创建自己的this,所以它没有自己的this,只会在自己作用域的上层继承this。所以箭头函数中this的指向在定义的时候就已经确定了,以后不会改变。(3)箭头函数继承的this点永远不会改变varid='GLOBAL';varobj={id:'OBJ',a:function(){console.log(this.id);},b:()=>{console.log(this.id);}};obj.a();//'OBJ'obj.b();//'GLOBAL'newobj.a()//undefinednewobj.b()//UncaughtTypeError:obj.bisnotaconstructor复制代码对象obj的方法b是使用箭头函数定义的,这个函数中的this在定义的全局执行环境中始终指向this。即使这个函数作为对象obj的方法被调用,this仍然指向Window对象。需要注意的是,定义对象的大括号{}不能形成单独的执行环境,它仍然处于全局执行环境中。(4)call()、apply()、bind()等方法不能改变箭头函数中this的方向varid='Global';letfun1=()=>{console.log(this.id)};乐趣1();//'Global'fun1.call({id:'Obj'});//'Global'fun1.apply({id:'Obj'});//'Global'fun1.bind({id:'Obj'})();//'Global'copycode(5)箭头函数不能用作构造函数。上面新步骤中已经提到了构造函数。其实第二步就是在函数中用this指向这个对象。但是由于箭头函数没有自己的this,而this指向外层的执行环境,不能改变指向,所以不能作为构造函数使用。(6)箭头函数没有自己的arguments箭头函数没有自己的arguments对象。访问箭头函数中的参数实际上是获取其外部函数的参数值。(7)箭头函数没有原型(8)箭头函数不能作为Generator函数使用,不能使用yeild关键字。Loader和Plugin有什么区别?Loader:直译为“装载机”。Webpack将所有文件都视为模块,但Webpack只能原生解析js文件。如果你想打包其他文件,你将使用加载器。所以Loader的作用就是赋予webpack加载和解析非JavaScript文件的能力。插件:直译为“插件”。Plugin可以扩展webpack的功能,使webpack更加灵活。在Webpack运行的生命周期中,会广播很多事件。Plugin可以监听这些事件,并适时通过Webpack提供的API改变输出结果。setTimeout、Promise、Async/Await的区别(一)setTimeoutconsole.log('scriptstart')//1.printscriptstartsetTimeout(function(){console.log('settimeout')//4.打印settimeout})//2.调用setTimeout函数,并定义完成后执行的回调函数console.log('scriptend')//3。printscriptstart//输出顺序:scriptstart->scriptend->settimeoutcopycode(2)PromisePromise本身是一个同步立即执行函数。在executor中执行resolve或reject时,此时是异步操作,然后/catch会先执行。主栈完成后,会调用resolve/reject中存储的方法,执行时打印p,就是打印的返回结果,一个Promise实例。console.log('scriptstart')letpromise1=newPromise(function(resolve){console.log('promise1')resolve()console.log('promise1end')}).then(function(){console.log('promise2')})setTimeout(function(){console.log('settimeout')})console.log('scriptend')//输出顺序:scriptstart->promise1->promise1end->scriptend->promise2->settimeoutcopycode当JS主线程执行到Promise对象时:promise1.then()的回调是一个taskpromise1被resolved或rejected:那么这个task会被放入当前的microtask队列eventloop.promise1ispending:该任务将被放入未来(可能是下一轮)事件循环的微任务队列中。setTimeout的回调也是一个task,即使是0ms也会被放入macrotask队列(3)async/awaitasyncfunctionasync1(){console.log('async1start');等待async2();console.log('async1end')}asyncfunctionasync2(){console.log('async2')}console.log('scriptstart');async1();console.log('scriptend')//输出顺序:scriptstart->async1start->async2->scriptend->async1end复制代码async函数返回一个Promise对象,当函数执行时,一旦遇到await,它会先返回,等待触发的异步操作完成,然后在函数体中执行下面的语句,可以理解为放弃线程,跳出async函数体。例如:asyncfunctionfunc1(){return1}console.log(func1())复制代码func1的结果实际上是一个Promise对象。所以也可以使用then来处理后续的逻辑。func1().then(res=>{console.log(res);//30})复制代码await表示等待,即async函数需要等待await之后的函数完成并返回结果(Promiseobject)在继续执行下面的代码之前。await通过返回一个Promise对象来实现同步的效果。浏览器如何管理和加载HTML5离线存储资源?上网时,浏览器发现html头有manifest属性,就会去请求manifest文件。如果是第一次访问该页面,浏览器会根据manifest文件的内容下载相应的资源并离线存储。如果页面被访问过并且资源已经离线存储,浏览器将使用离线资源加载页面,然后浏览器将新的清单文件与旧的清单文件进行比较,如果文件没有改变,donothing操作,如果文件发生变化,会重新下载文件中的资源并离线存储。离线时,浏览器会直接使用离线存储的资源。vuexvuex是专门为vue.js应用开发的状态管理器。它使用集中存储来管理应用程序所有组件的状态,并使用相应的规则来确保状态以可预测的方式变化。state:vuex使用单个状态树,其中包含所有应用程序级别的状态和一个对象。mutation:在vuex中改变state状态的唯一方法就是提交mutationaction:action提交mutation,而不是直接改变state。Action可以包含任意异步操作getter:相当于vue中的computed计算属性复制代码代码输出结果constfirst=()=>(newPromise((resolve,reject)=>{console.log(3);letp=newPromise((resolve,reject)=>{console.log(7);setTimeout(()=>{console.log(5);resolve(6);console.log(p)},0)resolve(1);});resolve(2);p.then((arg)=>{console.log(arg);});}));first().then((arg)=>{console.log(arg);});console.log(4);复制代码输出如下:374125Promise{:1}复制代码代码执行过程如下:首先进入Promise,打印出来3、然后输入下面的Promise,打印出7;遇到定时器,加入宏任务队列;执行Promisep中的resolve,状态变为resolved,返回值为1;先执行Promise中的resolve,状态变为resolved,返回值为2;遇到p的时候然后,将其添加到微任务队列中,遇到first()。然后,将其添加到任务队列中;执行外面的代码,打印出4;这样第一轮macrotask执行完毕,microtask队列中的task开始执行,依次打印出1和2;这样,microtask执行完毕,开始执行下一轮macrotasks。macrotask队列中有定时器,执行它,打印出5,因为执行已经变为resolved状态,所以resolve(6)不会再执行;最后console.log(p)打印Promise{:1};setTimeout模拟setInterval说明:使用setTimeout模拟setInterval的功能实现:constmySetInterval(fn,time){lettimer=null;constinterval=()=>{timer=setTimeout(()=>{fn();//真正的函数fninterval()将在time之后执行;//同时再次调用interval本身},time)}间隔();//开始执行//关闭定时器的返回函数return()=>clearTimeout(timer);}//测试constcancel=mySetInterval(()=>console.log(1),400);setTimeout(()=>{取消();},1000);//打印两次1复制代码函数中的参数是数组吗?如何将类数组转换为数组?是一个类数组的类,属于duck类型的类。看起来像一个数组,...operatorArray.fromArray.prototype.slice.apply(arguments)实现一个扇区用CSS实现一个扇区的思路和三角形基本一样,但是有more圆角样式实现90°扇区:div{border:100pxsolidtransparent;宽度:0;身高:0;边框半径:100px;border-top-color:red;}复制代码如果一个构造函数,绑定一个对象,用这个构造函数创建的实例会继承这个对象的属性吗?为什么?没有继承,因为根据这个绑定的四个规则,new绑定的优先级高于bind显示绑定。当通过new调用构造函数时,会创建一个新的对象,这个新对象会代替bind的对象绑定,作为这个函数的this,当这个函数没有返回对象时,返回这个新创建的对象What是尾调用,使用尾调用有什么好处?尾调用是指一个函数的最后一步调用另一个函数。代码执行是基于执行栈的,所以在一个函数中调用另一个函数时,会保留当前的执行上下文,然后创建另一个执行上下文加入栈中。如果使用尾调用,因为已经是函数的最后一步了,此时不需要保留当前的执行上下文,从而节省了内存。这就是尾调用优化。但是ES6的尾调用优化只在严格模式开启,普通模式无效。什么是CSS预处理器/后处理器?为什么要使用它们?预处理器,如:less、sass、stylus,用于预编译sass或less,增加css代码的复用性。Hierarchy、mixin、variables、loops、functions等,对于UI组件的编写和开发极为方便。后处理器,如:postCss,通常会根据css规范对完成的样式表中的css进行处理,使其更有效。目前最常见的做法是在css属性中添加浏览器特定的前缀,以实现跨浏览器的兼容。css预处理器在不考虑浏览器兼容性问题的情况下,为css增加了一些编程特性。可以使用CSS中的变量,简单的逻辑程序,函数等编程语言中的基本功能,可以让css更加简洁。增加适应性以及可读性、可维护性等。其他css预处理器语言:Sass(Scss)、Less、Stylus、Turbine、Switchcss、CSSCacheer、DTCss。使用理由:结构清晰,易于扩展,可轻松屏蔽浏览器私有语法差异,可轻松实现多重继承,完美兼容CSS代码,可应用于老项目新建一个构造函数,若函数返回return{},returnnull,return1,returntrue会发生什么?如果函数返回一个对象,那么new函数调用返回这个函数的返回对象,否则返回new创建的新对象什么是边距重叠问题?怎么解决?问题描述:两个块级元素的top和bottommargin可能合并(collapsed)为一个margin,它的大小会是margin值大的那个。这种行为是保证金崩溃。需要注意的是,脱离文档流的浮动元素和绝对定位元素的边距是不会塌陷的。重叠只会垂直发生。计算原理:折叠合并后外边距的计算原理是:如果都是正数,就找最大的那个。如果一正一负,则减去正值减去负值的绝对值,用0减去两个解中绝对值较大的一个:对于折叠的情况,主要有两种:兄弟重叠和父子重叠(1)兄弟重叠,最下面的元素变成了一个inlinebox:display:inline-block底部元素设置为float:float底部元素的位置值为absolute/fixed(2)父元素与父元素重叠Add:overflow:hidden父元素添加透明边框:border:1pxsolidtransparent子元素变为inlineBox:display:inline-block子元素添加浮动属性或定位CSS选择器及其优先级选择器格式优先级权重id选择器#id100类选择器#classname10属性选择器a[ref="eee"]10伪类选择器li:last-child10标签选择器div1伪元素选择器li:after1相邻兄弟选择器h1+p0子选择器ul>li0后代选择器lia0通配符选择器*0priorityforselectors:标签选择器,伪元素选择器:1类选择器,伪类选择器,属性选择器:10id选择器:100内联样式:1000注意:!important声明的样式优先级最高;如果优先级相同,则最后出现的样式生效;继承的样式具有最低的优先级;一般选择器(*)、子选择器(>)和相邻兄弟选择器(+)不在这四层中,所以它们的权重都是0;当样式表来源不同时,优先级顺序为:内联样式>内部样式>外部样式>浏览器自定义样式>浏览器默认样式。Proxy可以实现什么功能?在Vue3.0中,使用Proxy代替原来的Object.defineProperty,实现数据响应。Proxy是ES6的一个新特性,可以用来自定义对象中的操作。letp=newProxy(target,handler)复制代码target表示需要添加代理的对象,handler用于自定义对象中的操作,比如可以用来自定义set或者get功能。让我们通过Proxy实现一个数据响应:)},set(target,property,value,receiver){setBind(value,property)returnReflect.set(target,property,value)}}returnnewProxy(obj,handler)}letobj={a:1}}letp=onWatch(obj,(v,property)=>{console.log(`监控属性${property}更改为${v}`)},(target,property)=>{console.log(`'${property}'=${target[property]}`)})p.a=2//监听属性a的变化p.a//'a'=2copycode在上面的代码中,通过自定义的set和get函数,我们的将函数逻辑插入到原始逻辑中,当对象的任何属性被读取或写入时发送通知。当然,这是响应式实现的简单版本。如果你需要在Vue中实现响应式的方式,你需要在get中收集依赖,在set中分发更新。Vue3.0之所以使用Proxy来替代原有的API,是因为Proxy不需要一层层递归地为每个属性添加一个代理,一次性完成以上操作。性能更好,一些数据的更新在原来的实现中是无法监听到的,但是Proxy可以完美的监听到任何数据的变化。唯一的缺陷是浏览器。兼容性不好。下面说说对JS的理解。它是一种基于原型的动态语言。主要的独特之处在于,原型和原型链。严格来说,JS分为:语言标准部分(ECMAScript)+宿主环境部分。语言标准部分在2015年发布了ES6,引入了许多新特性,使得编写大型项目成为可能。更多的宿主环境部分包括浏览器宿主环境中的DOM+BOM等。在Node中,宿主环境包括一些文件、数据库、网络以及与操作系统的交互等。