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

2023年我的前端面试总结

时间:2023-03-27 22:40:56 HTML

TCP/IP五层协议TCP/IP五层协议与OSI七层协议的对应关系如下:应用层(applicationlayer):直接提供服务申请流程。应用层协议定义了应用进程之间通信和交互的规则。不同的应用有不同的应用层协议,如HTTP协议(万维网服务)、FTP协议(文件传输)、SMTP协议(电子邮件)、DNS(域名查询)等。Transportlayer(传输层):有时译为作为传输层,负责为两台主机中的进程提供通信服务。该层主要有以下两个协议:传输控制协议(TransmissionControlProtocol,TCP):提供面向连接的、可靠的数据传输服务,数据传输的基本单位是段(segment);用户数据报协议(UserDatagramProtocol,UDP):提供无连接的、尽力而为的数据传输服务,但不保证数据传输的可靠性。数据传输的基本单位是用户数据报。Internet层:有时也译作Internet层,负责为两台主机提供通信服务,并通过选择合适的路由将数据传送到目标主机。数据链路层(datalinklayer):负责将网络层下发的IP数据报封装成帧,并在链路的两个相邻节点之间传输帧,每个帧包含数据和必要的控制信息(如同步信息、地址信息、差错控制等)。物理层:保证数据可以在各种物理介质上传输,为数据传输提供可靠的环境。从上图可以看出,TCP/IP模型比OSI模型更加简洁,将应用层/表示层/会话层集成到应用层中。不同的设备在每一层工作。比如我们常用的交换机工作在数据链路层,而一般的路由器工作在网络层。每一层实现的协议也不同,即每一层的服务也不同。下图列出了各层的主要传输协议:同理,TCP/IP五层协议的通信方式也是点对点的通信:我来说说JSON.stringify的缺点是什么?1.如果obj中有时间对象,那么JSON.stringify后JSON.parse的结果,时间只会是字符串的形式,不会是对象的形式。2、如果有RegExp(正则表达式的缩写),Errorinobj对象,序列化的结果只会得到一个空对象;3.如果obj中有一个函数,undefined,序列化的结果会丢失这个函数或者undefined;4.如果obj中存在NaN、Infinity和-Infinity,则序列转换的结果会变成null5。JSON.stringify()只能序列化对象的可枚举自身属性。例如obj中的对象是由构造函数生成的,使用JSON.parse(JSON.stringify(obj))深拷贝后,对象的构造函数会被丢弃;6.如果对象中存在循环引用,则无法正确实现深拷贝;为什么0.1+0.2!=0.3,请详细说明原因,因为JS采用的是IEEE754双精度版本(64位),任何使用IEEE754的语言都有这个问题。我们都知道计算机用二进制表示小数,所以0.1用二进制表示为//(0011)表示一个循环0.1=2^-4*1.10011(0011)那么这个二进制怎么得到,我们可以计算出十进制的算术二进制不同于整数。乘法时只计算小数位,整数位作为每一位的二进制,得到的第一位为最高位。于是我们得到0.1=2^-4*1.10011(0011),那么0.2的计算基本如上所示,只需要去掉第一步的乘法,所以我们得到0.2=2^-3*1.10011(0011).回到IEEE754双精度。六十四位中,符号位占一位,整数位占十一位,其余五十二位均为小数位。因为0.1和0.2是无限循环的二进制,需要在小数点末尾判断是否进位(就像小数点四舍五入一样)。所以2^-4*1.10011...001在进位后变成2^-4*1.10011(0011*12次)010。然后将这两个二进制数相加得到2^-2*1.0011(0011*11次)0100,这个值计算为十进制0.300000000000000004先说一下原解,如下代码parseFloat((0.1+0.2).toFixed(10))JavaScript中的对象有一个特殊的原型内置属性,它实际上是对其他对象的引用。几乎所有对象在创建时都会为原型属性分配一个非空值。我们可以将这个属性作为一个备份仓库,当试图引用一个对象的某个属性时,就会触发一个get操作。第一步是检查对象本身是否具有此属性。有就用,没有就去原型里找。一层一层直到最顶层Object.prototype是基于原型扩展来描述原型链,什么是原型链,原型继承,ES5和ES6的继承和区别。Promise.all的描述:当所有的promise都变成fulfilled时,会返回一个fulfilled状态数组(所有promise的值)。只要一个失败,就返回第一个状态为rejected的promise实例的原因。实现:Promise.all=function(promises){returnnewPromise((resolve,reject)=>{if(Array.isArray(promises)){if(promises.length===0)returnresolve(promises);让结果=[];让计数=0;promises.forEach((item,index)=>{Promise.resolve(item).then(value=>{count++;result[index]=value;if(count===promises.length)resolve(result);},reason=>reject(reason));})}elsereturnreject(newTypeError("Argumentisnotiterable"));});}告诉我为什么数据是一个函数而不是一个对象?JavaScript中的对象是数据的引用类型。当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化。在Vue中,我们希望更多地复用组件,所以每个组件都需要有自己的数据,这样组件之间才不会相互干扰。所以组件的数据不能写成对象的形式,而要写成函数的形式。数据以函数返回值的形式定义,这样我们每复用一个组件,就会返回一个新的数据,也就是说每个组件都有自己私有的数据空间,各自维护自己的数据。会干扰其他部件的正常运行。参考前端高级面试题详细答案实现模板字符串解析说明:实现模板字符串中替换{{}}中变量的功能。核心:使用字符串替换方法str.replace(regexp|substr,newSubStr|function)将字符串替换为正则匹配。实现:functionrender(template,data){//模板字符串正则性/\{\{(\w+)\}\}/,添加g作为全局匹配方式,每次匹配都会调用下面的函数letcomputed=template.replace(/\{\{(\w+)\}\}/g,function(match,key){//match:匹配子串;key:匹配字符串returndata[key];});returncomputed;}//testlettemplate="我是{{name}},年龄{{age}},性别{{sex}}";letdata={name:"张三",age:18}console.log(呈现(模板,数据));//我是张三,18岁,性别undefinedSet,Map解构ES6提供了一种新的数据结构Set。类似于数组,但是成员的值都是唯一的,没有重复值。Set本身是一个构造函数,用于生成一个Set数据结构。ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但“键”的范围不限于字符串,各种类型的值(包括对象)都可以作为键。localStoragesessionStoragecookie有什么区别?localStorage:以键值对的形式存储。存储时间没有限制。除非记录被删除,否则它将永久生效。数据不能超过4k。同时,由于每个http请求都会携带cookies,所有的cookies只适合保存session标识等小数据。外部js文件先加载还是onload先执行,为什么?onloadisPromise.rejectPromise.reject=function(reason){returnnewPromise((resolve,reject)=>reject(reason));}代码输出问题functionfun(n,o){console.log(o)return{fun:function(m){returnfun(m,n);}};}vara=fun(0);a.乐趣(1);a.乐趣(2);a.fun(3);varb=fun(0).fun(1).fun(2).fun(3);varc=fun(0).fun(1);c.乐趣(2);(3);输出结果:undefined000undefined012undefined011这是一道关于闭包的题。对于fun方法,调用后返回一个对象。我们知道,在调用函数时,传入的实参个数少于函数声明中指定的形参个数,剩下的形参会被设置为未定义的值。所以console.log(o);将输出未定义。而a是fun(0)返回的对象。也就是说,函数fun中参数n的值为0,而在返回的对象中,需要一个参数n,而这个对象的作用域内没有n,则继续沿作用域到nextlevelscope寻找n,最后在函数fun中找到n,n的值为0。知道了这些,其他的操作就简单了,以此类推。让我们谈谈HTML页面中的WebWorker。如果脚本执行时页面的状态为非响应状态,则在脚本执行完成之前,页面不会变为响应状态。webworker是后台运行的js,独立于其他脚本,不会影响页面的性能。并通过postMessage将结果传回主线程。这样,在执行复杂操作时,不会阻塞主线程。如何创建webworker:检测浏览器对webworker的支持创建webworker文件(js、returnfunction等)创建webworker对象谈谈git常用操作gitbranch查看所有本地分支gitstatus查看当前状态gitcommit提交gitbranch-a查看所有分支gitbranch-r查看所有远程分支gitcommit-am"nit"提交并添加注释gitremoteaddorigingit@192.168.1.119:ndshowgitpushoriginmaster推送文件到服务器gitremoteshoworigin显示远程库origin中的资源gitpushoriginmaster:developgitpushoriginmaster:hb-dev关联本地库和服务器上的库gitcheckout--trackorigin/dev切换到远程dev分支gitbranch-Dmasterdevelop删除本地库developgitcheckout-bdev新建本地分支devgitmergeorigin/dev将分支dev与当前分支合并gitcheckoutdev切换到本地dev分支gitremoteshow查看远程库gitadd.gitrm文件名(包括路径)从git中删除指定文件gitclonegit://github.com/schacon/grit.git从服务器拉取代码gitconfig--list查看所有用户gitls-files查看提交的gitrm[文件名]删除一个文件gitcommit-a提交当前repos的所有改动gitadd[文件名]添加一个文件到gitindexgitcommit-v使用-v参数时,可以查看提交的区别gitcommit-m"Thisisthemessagedescribingthecommit"添加提交信息gitcommit-a-a代表add,将所有的改动添加到git索引中然后commitgitcommit-a-v一般提交命令gitlog查看你的commitloggitdiff查看没有暂存的更新gitrma.aremove文件(从暂存区和工作区删除)gitrm--cacheda.a删除文件(仅从暂存区删除)gitcommit-m"remove"删除文件(从Git中删除)gitrm-fa.a强制删除修改后的文件(从暂存区和工作区删除)gitdiff--cached或$gitdiff--staged查看未提交的更新gitstashpush将文件推送到临时空间gitstashpop从临时空间弹出文件。事件传播机制(事件流)冒泡和捕获Promise.resolvePromise.resolve=function(value){//1.如果value参数是一个Promise对象,则返回该对象不变if(valueinstanceofPromise)returnvalue;//2.如果value参数是一个有then方法的对象,将这个对象转为Promise对象,并立即执行其then方法if(typeofvalue==="object"&&'then'invalue){returnnewPromise((resolve,reject)=>{value.then(resolve,reject);});}//3.否则,返回一个状态为fulfilled的新Promise对象returnnewPromise(resolve=>resolve(value));}codeoutputvarA={n:4399};varB=function(){this.n=9999};varC=function(){varn=8888};B.prototype=A;C.prototype=A;varb=newB();varc=newC();A.n++console.log(b.n);console.log(c.n);输出结果:99994400分析:console.log(b.n),在寻找b.n的时候,先检查b对象本身是否有n属性,如果没有,就会去原型(prototype)中查找,执行varb=newB(),函数里面的this.n=9999(此时this指向b)返回b对象,b对象有自己的n属性,所以返回9999console.log(c.n),同理,执行varc=newC时(),c对象本身没有n属性,查找,发现原型(prototype)上的n属性,因为A.n++(此时对象A中的n为4400),所以返回4400。代码输出问题window.number=2;varobj={number:3,db1:(function(){console.log(this);this.number*=4;returnfunction(){console.log(this);this.number*=5;}})()}vardb1=obj.db1;db1();obj.db1();console.log(obj.number);//15console.log(window.number);//40的题目看起来有点乱,其实考察this指向什么:执行db1()时,this指向全局作用域,所以window.number4=8,然后执行匿名函数,所以window.number5=40;执行obj.db1();时,this指向obj对象,执行匿名函数,所以obj.numer*5=15。JSONP跨域实现JSONP核心原则:脚本标签不受同源策略约束,可用于跨域请求。优点是兼容性好,但只能用于GET请求;实现:constjsonp=(url,params,callbackName)=>{constgenerateUrl=()=>{letdataSrc="";for(letkeyinparams){if(params.hasOwnProperty(key)){dataSrc+=`${key}=${params[key]}&`}}dataSrc+=`callback=${callbackName}`;返回`${url}?${dataSrc}`;}returnnewPromise((resolve,reject)=>{constscriptEle=document.createElement('script');scriptEle.src=generateUrl();document.body.appendChild(scriptEle);window[callbackName]=data=>{resolve(data);document.removeChild(scriptEle);}});}src和href的区别src和href都是用来引用外部资源的,区别如下:resource,它指向的内容会嵌入到当前标签的位置。src会把它指向的资源下载并应用到文档中,比如请求js脚本。浏览器在解析该元素时,会暂停其他资源的下载和处理,直到该资源加载、编译、执行完毕,所以一般js脚本都会放在页面底部。href:表示超文本引用,指向一些网络资源,与当前元素或本文档建立链接关系。当浏览器识别出它指向的文件时,它会在不停止处理当前文档的情况下并行下载资源。常用于a和link等标签。