当前位置: 首页 > 后端技术 > Node.js

花了一周时间整理的前端面试题,主要是干货

时间:2023-04-03 13:06:48 Node.js

websocketWebsocket和http一样,是基于tcp的,一种可靠的双向通信协议,是基于tcp的,是一种持久化协议。websocket和http有什么区别?相同点是应用层的协议都是基于tcp这个可靠的协议。不同之处在于websocket是一个持久化协议。Websocket是一种双向通信协议,模拟socket协议,可以双向发送信息,而HTTP是单向websocket,可以在服务端主动向客户端发送信息,而http服务端只能通过客户端主动请求。请描述cookie、sessionStorage和localStorage的区别?相同点:都存储在客户端。不同点的存储大小。cookie数据大小不能超过4k。sessionStorage和localStorage虽然也有存储大小的限制,但是比cookie大很多,可以达到5M甚至更大。有效时间localStorage存储持久化数据,除非主动删除数据,否则关闭浏览器后数据不会丢失;sessionStorage数据在当前浏览器窗口关闭后自动删除。cookie设置的cookie有效期至cookie过期时间。即使窗口或浏览器关闭,数据与服务器的交互,cookie数据也会自动传给服务器,服务器也可以将cookie写入客户端sessionStorage,localStorage不会自动保存数据发送到服务器,本地只保存JS的类型?基本类型undefinednullNumberStringBoolean复杂类型Objectjs变量根据存储方式来区分,有哪些类型,表达了它的特点。空间。特殊引用类型:函数与引用类型相同↑特殊引用类型只是函数。由于函数的特殊性,与JS中通过typeof获取的那些类型有点区别?numberstringundefinedobject的6种类型:null和数组是objectfunctionboolean注意:typeof无法详细区分引用类型的类型,函数除外。只能准确区分值类型的类型如:typeof{}//objecttypeof[]//objecttypeofnull//objecttypeofconsole.log//function函数是一种特殊类型,所以typeof可以区分什么时候使用===以及何时使用==?由于以下原因,请尽可能使用===。一致性:使用==对一致性没有好处,所以要提前避免。一般来说,===是最简单的运算符,因为它不需要类型转换,所以相对来说,速度也会更快。==会进行类型转换,==的使用很容易混淆。可以参考判断对象的属性是否存在varobj={};if(obj.a==null){//这是相对于:obj.a===null||obj.a===undefined的简写,JQ源码推荐写法}判断函数参数是否存在functionfn(a,b){if(b==null){//这相当于b===null||的简写b===undefined}}如何理解JSON?从纯JS的角度来看,JSON是一个对象,只有两个APIJSON.stringify({a:10,b:30})//把对象转成字符串JSON.parse('{"a":10,"b":30}')//将JSON格式的字符串转换为对象JSON也是一种轻量级的文本数据交换格式。js中的内置函数有哪些?ObjectArrayBooleanNumberStringFunctionDateRegExpError判断一个变量会被认为是true还是falsevara=100;控制台日志(!!a);//truewindow.onload和DOMContentLoaded的区别?window.onload:页面中所有数据加载完成后执行,包括图片、css等DOMContentLoaded:DOM结构加载完成后执行,需要等待图片等资源加载完成加载。简单介绍一下如何实现一个模块加载器,类似requires.js的基本功能可以参考这篇博文:https://github.com/youngwind/...实现数组的随机排序//这个方法最简单,效果一般,每个元素还是有很大概率在原来的位置arr.sort(function(){returnMath.random()-0.5;});//Fisher–YatesshuffleFisherYatesrandomscramblingalgorithm)出现在位置附近!!!推荐//算法思路:从0~i(i从n-1变为0)随机获取一个下标,与最后一个元素(i)交换。vararr=[5,8,59,56];函数随机播放(arr){vari=arr.length,t,j;while(i){j=Math.floor(Math.random()*i--);t=arr[i];arr[i]=arr[j];arr[j]=t;}}shuffle(arr)console.log(arr);//[56,8,5,59]原型与原型链什么是原型链?原型链是给构造函数的。比如我创建一个函数,通过变量new创建一个函数,那么这个函数就会继承创建处理函数的属性。如果访问这个函数的属性,如果属性没有写在new处理的变量中,那么就会往上走,按照原型一步步往上找。这个搜索过程称为原型链。原型规则所有引用类型(数组、对象、函数)都具有对象的特殊特性,即可以自由扩展属性(Null除外,这纯属偶然)。所有的引用类型(数组、对象、函数)都有一个__proto__属性,也称为隐式原型,该属性值是一个普通对象的所有函数,都有一个原型属性,也可以称为显式原型,而该属性值是普通对象(数组、对象、函数)的所有引用类型,__proto__属性值指向其构造函数的原型属性值。当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,就会去它的__proto__中去寻找。由于它的隐式原型等于它的显式原型,所以它也会去原型中寻找。构造函数Foo(name,age){this.name=name;this.age=age;}varfoo=newFoo('h1',25);varfoo2=newFoo('h1',250);console.log(foo,foo2);//循环对象自身属性varitem;for(iteminfoo){//只遍历对象自身的属性,过滤掉对象的显式原型if(foo.hasOwnProperty(item)){console.log(item)}}描述new一个对象的过程objectthis指向这个新的对象来执行代码,也就是assignreturnthis给this。默认有return,不用写怎么判断一个变量是数组类型vararr=[1,2,3];console.log(Array.isArray(arr));//true//instanceof操作符用于测试构造函数的原型属性是否出现在对象原型链的任何位置console.log(arrinstanceofArray)//true写一个原型继承函数的例子Elem(id){this.dom=document.getElementById(id);}元素。prototype.html=function(val){vardom=this.dom;if(val){dom.innerHTML=val;归还这个;//对于链调用}else{returndom.innerHTML;}}Elem.prototype.on=function(type,fn){v??ardom=this.dom;dom.addEventListener(类型,fn);}varh1=newElem('h1');h1.html("你被修改了").on('click',function(){console.log(this)})作用域和闭包什么是作用域?`范围是变量。例如,我创建了一个包含另一个函数的函数。然后这个变量中有3个作用域。全局作用域>函数作用域>内部函数作用域。抬头。`变量提升变量定义函数声明的理解(注意和函数表达式的区别)预解析this的使用场景注意:this的值只有在执行时才能确定,不能在定义时确定.作为构造函数执行并作为对象属性执行。执行调用应用绑定函数f1(name,age){console.log(name,age)console.log(this);//这是x对象}f1.apply({x:'我是这个'},["seek",20]);f1.call({x:'我是这个'},"seek",20);//使用bind改变this时,需要函数表达式varf1=function(name,age){console.log(name,age)console.log(this);//thisisthexobject}.bind('Iamtheboundthis')f1("seek",20)Closure`当一个函数的返回值是另一个函数,并且如果返回的函数调用了其父类内部的其他变量function,如果返回的函数在外面执行,就会产生一个闭包。表现形式:使函数外部可以调用函数内部定义的变量。`闭包使用场景函数作为返回值函数fn(){vara=10;返回函数(){console.log(a);//a是一个自由变量,从父作用域中搜索。}}varf1=fn();vara=20;f1();//10个函数作为参数传递functionfn(){vara=10;返回函数(){console.log(a);}}varfn1=fn();functionfn2(fn){v??ara=20;fn();}fn2(fn1);//10作用域怎么理解?自由变量作用域链,即自由变量搜索闭包JS的两个场景创建了10个a标签,点击时弹出对应序号(测试点:scope)varstr,a;for(a=0;a<10;a++){str=document.createElement("a");str.innerHTML=a+"点我"+"
";document.body.appendChild(str);(function(a){str.addEventListener("click",function(e){e.preventDefault();console.log(a)})})(a)}什么是异步什么是同步?同步是阻塞模式,异步是非阻塞模式。异步:响应用户请求而不等待操作完成。例如:ajax、imgloading、setTimeout、setInterval同步:必须等待操作完成才返回结果。ArrayAPIvararr=[2,3,9,0];forEach遍历所有元素arr.forEach(function(item,index){console.log(item)//2390console.log(index)//0123})every判断所有元素是否满足条件varresult=arr.every(function(item,index){if(item<4){returntrue;}})console.log(result);//false,因为9不小于4some判断是否至少有一个元素满足条件varresult=arr.some(function(item,index){if(item<4){returntrue;}})console.log(结果);//true因为2,3,0小于4sortsortvarresult=arr.sort(function(a,b){//returna-b;//positiveorderreturnb-a;//reverseorder//returnreturnMath.random()-0.5;//最简单的随机数组排序,不推荐})console.日志(结果);//[9,3,2,0]map将元素重新组合生成新数组//map的应用范围很广,学着想varresult=arr.map(function(item,index){return'

'+item+'

';})console.log(result);//["

;2

","

3

","

9

","

0

"]过滤满足条件的过滤元素,more常用varresult=arr.filter(function(item,index){if(item>=3){returntrue;}})console.log(result);//[3,9]获取2019-的格式03-23DatefunctionformatDate(dt){if(!dt){//如果不传参数,默认为当前时间dt=newDate();}varyear=dt.getFullYear();varmonth=dt.getMonth()+1;varday=dt.getDate();if(month<=10){month='0'+month;}if(day<=10){day='0'+day;}returnyear+'-'+month+'-'+day;}vardate=formatDate();console.log(date);//2019-03-23获取随机数,要求字符串格式长度一致varrandom=Math.random();random=random+'0'.repeat(10);//repeat重复10个0,防止随机数少于10位random=random.slice(0,10)console.log(random);//0.70728618每次只返回10位字符串写入一个遍历对象andarrayforeachfunctionfunctionforeach(info,fn){//数组处理if(infoinstanceofArray){info.forEach(fn)}else{//对象处理for(keyinobj){fn(key,obj[key])}}}//使用方法varobj={x:'我是x',y:'我是y'};foreach(obj,function(key,value){console.log(value);//我是x,我是y})vararr=[5,8,9];foreach(arr,function(elem,index){console.log(elem);//5,8,9})Web_API写一个通用的事件监听函数functionbindEvent(elem,type,fn){elem.addEventListener(type,fn)}//使用方法bindEvent(id,'click',function(e){console.log(e)})bindEvent(a,'click',function(e){e.preventDefault();//阻止默认事件})对于无限加载流的页面,如何给每个特定标签添加事件//使用代理,由父级帮助完成a1a2ddda5
div1.addEventListener('点击',function(e){if(e.targett.nodeName=="A"){alert(e.target.innerHTML)}})完善通用绑定事件的功能,包括代理//HTML结构a1a2ddda5
不使用代理
//functionbindEvent(elem,type,selector,fn){if(fn==null){fn=selector;选择器=空;}elem.addEventListener(type,function(e){vartarget;if(selector){target=e.target;//matches()方法用于检测字符串是否匹配给定的正则表达式if(target.matches(selector)){fn.call(target,e);}}else{fn.call(e);}})}//使用代理bindEvent(div1,'click','a',function(e){console.log(this)})//不使用代理bindEvent(div2,'click',function(e){//callchangesthispointtoeconsole.log(this.toElement.innerHTML)})三个可以跨域的标签//用于dot统计//使用CDN//使用JSONP的优缺点March10interviewclosures在JS中,函数内部的值无法在函数外部访问,可以使用闭包这样做。优点:使用闭包可以让局部变量模拟全局变量,但只能被特定的函数调用。全局变量可能会导致命名冲突。使用闭包时不必担心这个问题,因为它们是私有的并且增强了封装性。缺点由于闭包常驻内存,会增加内存占用。使用不当很容易造成内存泄漏,降低程序的性能。按需导入,实现模块导入?http请求缓存头Expires详解Expires:由http1.0推出,指的是服务器返回文件的有效期,但实际上这是有缺陷的。如果本地时间改为2118,Expires时间无论如何都会过期。Last-Modified:由http1.0引入,指服务器文件的最后修改时间。浏览器会向服务器发送一个带有If-Modified-Since的请求,并与服务器文件修改的last-Modified时间进行比较。如果时间不同,get数据返回200,否则返回304,调用浏览器本地硬盘的缓存。Cache-Control:由http1.1推出,指的是文件缓存的有效期。.max-age:单位为s,设置文件的最大缓存时间,用得最多。public:缓存可以被多个用户共享,例如360浏览器可以登录不同的账户,计算机系统可以在不同的账户之间切换private:只对单个用户私有,不被多个用户共享no-缓存:不会被缓存。no-store:不允许存储ETag:http1.1推出,这个版本号是服务器随机生成的,浏览器会带上If-None-Match向服务器发送请求,与修改后的进行比较服务器文件ETag的版本,如果版本号不同,则获取数据返回200,否则返回304,调用浏览器本地硬盘的缓存。这种方法比Last-Modified更可靠。