CDN原理CDN和DNS有着千丝万缕的联系。首先我们来看一下DNS域名解析过程。在浏览器中输入的解析过程如下:(1)查看浏览器缓存(2)查看操作系统缓存,如常用的hosts文件(3)查看路由器缓存(4)如果前面的步骤没有找到,它会查询ISP(InternetServiceProvider)的LDNS服务器(5)如果LDNS服务器没有找到,就会请求根域名服务器(RootServer)进行解析,分为以下几个步骤:根服务器返回.com、.cn、.org等顶级域名(TLD)服务器的地址,本例中会返回.com地址,然后向top-发送请求一级域名服务器,然后返回二级域名(SLD)服务器的地址。本例返回.test的地址,然后向二级域名服务器发送请求,再返回通过域名查询到的目标IP,本例将返回www.test.com的地址。LocalDNSServer会将结果缓存起来返回给用户。CDN在系统中缓存的工作原理:(1)用户未使用CDN缓存资源的过程:浏览器使用DNS对域名进行解析(即上述DNS解析过程),而依次获取域名对应的IP地址。浏览器根据获取到的IP地址,向该域名的服务主机发送数据,请求服务器向浏览器返回响应数据。(2)用户使用CDN缓存资源过程:对于点击数据的URL,经过本地DNS系统解析后,发现该URL对应一个CDN专用的DNS服务器,DNS系统会将CNAME指向的CDN专用DNS服务器的域名解析权。CND的专用DNS服务器将CND的全局负载均衡设备的IP地址返回给用户。用户向CDN的全局负载均衡设备发起数据请求。CDN的全局负载均衡器根据用户的IP地址和用户请求的内容URL选择用户。所属区域的区域负载均衡设备告诉用户向该设备发起请求。区域负载均衡设备选择合适的缓存服务器提供服务,并将缓存服务器的IP地址返回给全局负载均衡设备。全局负载均衡设备向服务器发送用户的IP地址返回给用户。用户向缓存服务器发起请求,缓存服务器响应用户的请求,将用户需要的内容发送给用户终端。如果缓存服务器没有用户想要的内容,缓存服务器会向上级缓存服务器请求内容,以此类推,直到获取到需要的资源。最后还是没有,就回到自己的服务器去获取资源。CNAME(意思:别名):在域名解析中,实际解析的是指定域名对应的IP地址,或者该域名的一个CNAME,然后根据这个CNAME查找对应的IP地址。Object.isImplementationTitle说明:Object.is不会对被比较的两个值进行类型转换,更类似于===,但也有一些区别。1、NaN在===中不相等,但在Object.is中相等2、+0和-0在===中相等,但在Object.is中不相等实现代码如下:Object.is=function(x,y){if(x===y){//目前的情况只有一种情况比较特殊,即+0-0//Ifx!==0,Thenreturntrue//Ifx===0,需要判断+0和-0,可以直接用1/+0===Infinity和1/-0===-Infinity来判断returnx!==0||1/x===1/y;}//对于x!==y的情况,只需要判断是否为NaN即可。如果x!==x,则表示x是NaN。同理,y相同//当x和y均为NaN时,返回truereturnx!==x&&y!==y;};Promise.all和Promise.race的区别(1)Promise.allPromise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值不同。成功时返回结果数组,失败时返回最先被拒绝的值。在Promise.all中,传入一个数组,返回一个数组,进行映射。传入的promise对象返回的值是按照顺序排列在数组中的,但是注意它们执行的顺序并不是按照Sequential的,除非iterable为空。需要注意的是,Promise.all获取到的成功结果数组中的数据顺序与Promise.all接收到的数组顺序是一致的,这样当发送多个请求,根据请求顺序,可以使用Promise.all来解决。(2)Promise.race,顾名思义,Promse.race的意思是race,意思是Promise.race([p1,p2,p3])中的结果,无论哪个结果很快得到,就返回那个结果,不管结果如何本身成功了还是失败了。当你想做某事的时候,可以用这个方法解决:Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})codeoutputresultvarF=function(){};Object.prototype.a=function(){console.log('a');};Function.prototype.b=function(){console.log('b');}varf=newF();f.a();f.b();F.a();F.b()输出结果:aUncaughtTypeError:f.bisnotafunctionAb分析:f不是Function的实例,因为不是构造函数,调用上的相关属性和方法Function原型链只能访问Object原型链。所以f.a()输出a,f.b()报错。F是构造函数,F是构造函数Function的实例。因为FinstanceofObject===true,且FinstanceofFunction===true,可以得出F是Object和Function的实例,即F既可以访问a,也可以访问b。所以F.a()输出a,F.b()输出b。数据类型判断typeof可以正确识别:Undefined、Boolean、Number、String、Symbol、Function等类型的数据,但对于其他类型的数据,如Null、Date等,判断数据类型会不准确按类型。但是可以使用Object.prototype.toString来实现。functiontypeOf(obj){-letres=Object.prototype.toString.call(obj).split('')[1]-res=res.substring(0,res.length-1).toLowerCase()-返回res//更好的写法+returnObject.prototype.toString.call(obj).slice(8,-1).toLowerCase()}typeOf([])//'array'typeOf({})//'object'typeOf(newDate)//'date'Vue路由守卫是什么,如何设置,使用场景等两种常用的路由守卫:router.beforeEach和router.afterEach每个守卫方法接收三个参数:to:route:即将进入的目标路由对象from:route:当前导航离开的路由next:功能:必须调用该方法来解析这个钩子。在项目中,一些关于路由跳转的信息判断,一般都是在beforeEach钩子函数中进行。判断是否登录,是否获取相应的路由权限等。为什么需要浏览器缓存?对于浏览器的缓存,主要是针对前端静态资源的。最好的效果是在发起请求后,拉取相应的静态资源存储在本地。如果服务器的静态资源没有更新过,那么下次请求直接从本地读取即可。如果服务器的静态资源已经更新,那么当我们再次请求时,我们会去服务器拉取新的资源并保存。本地。这大大减少了请求的数量,提高了网站的性能。这将使用浏览器的缓存策略。所谓浏览器缓存,就是浏览器将用户请求的静态资源存储在计算机的本地磁盘中。浏览器再次访问时,可以直接从本地加载,无需去服务器端请求。使用浏览器缓存有以下优点:减轻了服务器的负担,提高了网站的性能,加快了客户端网页的加载速度,减少了冗余的网络数据传输。深拷贝浅拷贝:只考虑对象类型。functionshallowCopy(obj){if(typeofobj!=='object')returnletnewObj=objinstanceofArray?[]:{}for(letkeyinobj){if(obj.hasOwnProperty(key)){newObj[key]=obj[key]}}returnnewObj}简单深拷贝:只考虑和构建公共对象属性-in对象和函数不被考虑。functiondeepClone(obj){if(typeofobj!=='object')返回;varnewObj=objinstanceof数组?[]:{};for(varkeyinobj){if(obj.hasOwnProperty(key)){newObj[key]=typeofobj[key]==='object'?deepClone(obj[key]):obj[key];}}returnnewObj;}Complexdeepclone:在简单版本的基础上,还考虑了Built-inobjects如Date、RegExp等对象和函数,解决了循环引用的问题。constisObject=(target)=>(typeoftarget==="object"||typeoftarget==="function")&&target!==null;functiondeepClone(target,map=newWeakMap()){if(map.get(target)){返回目标;}//获取当前值的构造函数:获取其类型letconstructor=target.constructor;//检查当前对象目标是否匹配正则和日期格式对象if(/^(RegExp|Date)$/i.test(constructor.name)){//创建特殊对象的新实例(正则类/日期类)返回新的构造函数(目标);}if(isObject(target)){map.set(target,true);//为循环引用标记对象constcloneTarget=Array.isArray(target)?[]:{};for(letpropintarget){if(target.hasOwnProperty(prop)){cloneTarget[prop]=deepClone(target[prop],map);}}返回克隆目标;}else{返回目标;}}标签的作用是什么?如何使用?label标签定义表单控件之间的关系:当用户选择label标签时,浏览器会自动将焦点转到与label标签相关的表单控件上。方法一:
