当前位置: 首页 > news >正文

公司网站未备案吗查看wordpress版本号

公司网站未备案吗,查看wordpress版本号,一般通过男性,wordpress如何编辑网页加代码2020最全的前端面试指南#xff0c;一个多月 1.8w 字的面试经验积累#xff0c;凭借它最终成功入职大厂……今年的金三银四刚好赶上疫情#xff0c;很多大公司都停止招聘甚至裁员#xff0c;想跳槽的小伙伴被打的措手不及。需求减少要求肯定随之提高#xff0c;谨以此面经…2020最全的前端面试指南一个多月 1.8w 字的面试经验积累凭借它最终成功入职大厂……今年的金三银四刚好赶上疫情很多大公司都停止招聘甚至裁员想跳槽的小伙伴被打的措手不及。需求减少要求肯定随之提高谨以此面经献给在如此艰难之时逆风而动、勇敢坚强的你~前言今年问的难度和深度应该比前几年有所增加下面从总体分析和重要点两个维度来分析一下总体分析前端问的最多的还是 js基础、计算机网络基础等建议在此处多下功夫。而 css 相关的很少问到最多也就问个三栏布局、两栏布局、水平垂直居中把前两节看了面试基本没啥问题。框架 React/Vue 相关的在中小公司问的多一些差不多占到面试时间的一半。而大厂不爱问框架更注重基础因为入职之后让你用哪个框架你就用哪个框架…即使问也是问比较底层的东西比如 vue 的双向绑定原理。重要点最后再列举几个重要的点无论大中小公司基本都会问的性能优化以及每个优化点具体怎么做每个点都可能延伸了问。比如你说异步加载面试官会追问异步加载的方法deffer 和 async 的区别。你说充分利用缓存面试官会问缓存都有哪些方式什么是强缓存什么是协商缓存它们的返回码分别是什么哪些资源存在 memory cache 哪些存在 disk cache…http/https/http2.0。三次握手四次挥手https 为什么安全为什么慢跟 http 的区别http2.0 都有哪些优化浏览器输入url到看到页面的整个流程…安全类的常见的攻击手段记好 CSRF 和 XSS 攻击的原理和防范措施就好了。ES6 新特性还有针对 var 和 let 的各种变态题。跨域的几种方式。除了以上这些大公司还喜欢让你介绍一个你觉得做的比较好的项目有哪些亮点。这块一定要好好准备你讲的项目用到的技术最好能够了解的非常深入避免给自己挖坑。这篇文章内容比较多后面会出一个精简重点版便于复习敬请期待~一、页面布局三栏布局题目假设高度已知请写出三栏布局其中左栏、右栏宽度各为 300px中间自适应。解答可以有很多种布局方式这里列出五种float布局absolute布局flex布局table布局grid布局代码如下!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitle三栏布局/titlelink relstylesheet hrefstyle typetext/css mediascreenhtml *{margin: 0;padding: 0;}/style /head bodysection classlayout floatstyle typetext/css mediascreen.layout.float .wrapperdiv{min-height: 100px;}.layout.float .left{float: left;width: 300px;background: red;}.layout.float .center{background: yellow;}.layout.float .right{float: right;width: 300px;background: blue;}/stylearticle classwrapperdiv classleft/divdiv classright/divdiv classcenterh1float布局/h11.我是float布局的中间部分2.我是float布局的中间部分/div/article/sectionsection classlayout absolutestyle typetext/css mediascreen.layout.absolute .wrapper{width: 100%;margin-top: 20px;}.layout.absolute .wrapperdiv{min-height: 100px;}.layout.absolute .left{position: absolute;left: 0;width: 300px;background: red;}.layout.absolute .center{position: absolute;left: 300px;right: 300px;background: yellow;}.layout.absolute .right{position: absolute;right: 0;width: 300px;background: blue;}/stylearticle classwrapperdiv classleft/divdiv classcenterh1absolute布局/h11.我是absolute布局的中间部分2.我是absolute布局的中间部分/divdiv classright/div/article/sectionsection classlayout flexstyle typetext/css mediascreen.layout.flex .wrapper{width: 100%;min-height: 100px;display: flex;margin-top: 140px;}.layout.flex .left{width: 300px;background: red;}.layout.flex .center{flex: 1;background: yellow;}.layout.flex .right{width: 300px;background: blue;}/stylearticle classwrapperdiv classleft/divdiv classcenterh1flex布局/h11.我是flex布局的中间部分2.我是flex布局的中间部分/divdiv classright/div/article/sectionsection classlayout tablestyle typetext/css mediascreen.layout.table .wrapper{display: table;width: 100%;min-height: 100px;margin-top: 20px;}.layout.table .left{display: table-cell;width: 300px;background: red;}.layout.table .center{display: table-cell;background: yellow;}.layout.table .right{display: table-cell;width: 300px;background: blue;}/stylearticle classwrapperdiv classleft/divdiv classcenterh1table布局/h11.我是table布局的中间部分2.我是table布局的中间部分/divdiv classright/div/article/sectionsection classlayout gridstyle typetext/css mediascreen.layout.grid .wrapper{display: grid;grid-template-columns: 300px auto 300px;grid-template-rows: 100px;width: 100%;margin-top: 20px;}.layout.grid .left{background: red;}.layout.grid .center{background: yellow;}.layout.grid .right{background: blue;}/stylearticle classwrapperdiv classleft/divdiv classcenterh1grid布局/h11.我是grid布局的中间部分2.我是grid布局的中间部分/divdiv classright/div/article/section /body /html 复制代码面试时至少写出三种哦。接下来问题可能会有三个延伸方向每种方案的优缺点如果高度不固定实践中一般用哪种以上几种方案的兼容性如何每种布局的优缺点1. float 布局优点 比较简单兼容性也比较好。只要清除浮动做的好是没有什么问题的缺点浮动元素是脱离文档流要做清除浮动这个处理不好的话会带来很多问题比如高度塌陷等。2. 绝对布局优点很快捷设置很方便而且也不容易出问题缺点绝对定位是脱离文档流的意味着下面的所有子元素也会脱离文档流这就导致了这种方法的有效性和可使用性是比较差的。3. flex 布局优点简单快捷缺点不支持 IE8 及以下4. table布局优点实现简单代码少缺点当其中一个单元格高度超出的时候两侧的单元格也是会跟着一起变高的而有时候这种效果不是我们想要的。5. grid布局跟 flex 相似。水平垂直居中absolute 负margin这种方式比较好理解兼容性也很好缺点是需要知道子元素的宽高div classoutdiv classinner12345/div /divstyle typetext/css.out{position: relative;width: 300px;height: 300px;background: red;}.inner{position: absolute;width: 100px;height: 100px;background: yellow;left: 50%;top: 50%;margin-left: -50px;margin-top: -50px;} /style 复制代码absolute auto margin这种方法兼容性也很好缺点是需要知道子元素的宽高style typetext/css.out{position: relative;width: 300px;height: 300px;background: red;}.inner{position: absolute;width: 100px;height: 100px;background: yellow;left: 0;top: 0;right: 0;bottom: 0;margin: auto;} /style 复制代码absolute calc这种方法的兼容性依赖于 calc且也需要知道宽高style typetext/css.out{position: relative;width: 300px;height: 300px;background: red;}.inner{position: absolute;width: 100px;height: 100px;background: yellow;left: calc(50% - 50px);top: calc(50% - 50px);} /style 复制代码absolute transform兼容性依赖 translate不需要知道子元素宽高style typetext/css.out{position: relative;width: 300px;height: 300px;background: red;}.inner{position: absolute;background: yellow;left: 50%;top: 50%;transform: translate(-50%, -50%);} /style 复制代码tablecss新增的table属性可以让我们把普通元素变为table元素的显示效果通过这个特性也可以实现水平垂直居中。这种方法兼容性也不错。style typetext/css.out{display: table-cell;width: 300px;height: 300px;text-align: center;vertical-align: middle;background: red;}.inner{display: inline-block;background: yellow;width: 100px;height: 100px;} /style 复制代码flexflex 实现起来比较简单三行代码即可搞定。可通过父元素指定子元素的对齐方式也可通过 子元素自己指定自己的对齐方式来实现。第二种方式见 grid 布局。style typetext/css.out{display: flex;justify-content: center;align-items: center;width: 300px;height: 300px;background: red;}.inner{background: yellow;width: 100px;height: 100px;} /style 复制代码gridgrid 布局也很强大大体上属性跟 flex 差不多。//方法一父元素指定子元素的对齐方式 style typetext/css.out{display: grid;align-content: center;justify-content: center;width: 300px;height: 300px;background: red;}.inner{background: yellow;width: 100px;height: 100px;} /style//方法二子元素自己指定自己的对齐方式 style typetext/css.out{display: grid;width: 300px;height: 300px;background: red;}.inner{background: yellow;width: 100px;height: 100px;align-self: center;justify-self: center;} /style 复制代码页面布局小结语义化掌握到位页面布局理解深刻CSS基础知识扎实思维灵活且积极上进代码书写规范二、CSS盒模型CSS盒模型是前端的基石这个问题由浅入深由易到难可以依次问出下面几个问题基本概念标准模型 IE模型标准模型 和 IE模型的区别CSS如何设置这两种模型JS如何设置和获取盒模型对应的宽和高实例题根据盒模型解释边距重叠BFC边距重叠解决方案1、基本概念所有HTML元素可以看作盒子在CSS中box model这一术语是用来设计和布局时使用。CSS盒模型本质上是一个盒子封装周围的HTML元素它包括边距边框填充和实际内容。盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。下面的图片说明了盒子模型(Box Model)2、标准模型与IE模型的区别标准模型与 IE 模型的区别在于宽高的计算方式不同。标准模型计算元素的宽高只算 content 的宽高IE模型是 content padding border 的总尺寸。假如 content 宽高是 100100pxpadding 为 10pxborder为 10pxmargin为10px那么在标准模型下这个元素的宽为 100px高为 100px。IE模型下宽为 100px 210px(左右padding) 210px(左右border) 140px;高为 100px 210px(上下padding) 2*10px(上下border) 140px;3、如何设置这两种模型//设置标准模型 box-sizing: content-box; //设置IE模型 box-sizing: border-box; 复制代码box-sizing 的默认值是 content-box即默认标准模型。4、JS如何设置盒模型的宽和高假设已经获取的节点为 dom//只能获取内联样式设置的宽高 dom.style.width/height//获取渲染后即时运行的宽高值是准确的。但只支持 IE dom.currentStyle.width/height//获取渲染后即时运行的宽高值是准确的。兼容性更好 window.getComputedStyle(dom).width/height;//获取渲染后即时运行的宽高值是准确的。兼容性也很好一般用来获取元素的绝对位置getBoundingClientRect()会得到4个值left, top, width, height dom.getBoundingClientRect().width/height; 复制代码5、BFC什么是 BFCBlock Formatting Context块级格式化上下文。在解释什么是BFC之前我们需要先知道Box、Formatting Context的概念。Boxcss布局的基本单位Box 是 CSS 布局的对象和基本单位 直观点来说就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性决定了这个 Box 的类型。 不同类型的 Box 会参与不同的 Formatting Context一个决定如何渲染文档的容器因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子block-level box: display 属性为 block, list-item, table 的元素会生成 block-level box。并且参与 block fomatting contextinline-level box: display 属性为 inline, inline-block, inline-table 的元素会生成 inline-level box。并且参与 inline formatting contextrun-in box: css3 中才有 这儿先不讲了。Formatting ContextFormatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域并且有一套渲染规则它决定了其子元素将如何定位以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。BFC的布局规则内部的Box会在垂直方向一个接一个地放置。Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。每个盒子块盒与行盒的margin box的左边与包含块border box的左边相接触(对于从左往右的格式化否则相反)。即使存在浮动也是如此。BFC的区域不会与float box重叠。BFC就是页面上的一个隔离的独立容器容器里面的子元素不会影响到外面的元素。反之也如此。计算BFC的高度时浮动元素也参与计算。如何创建BFCfloat的值不是none。position的值不是static或者relative。overflow的值不是visible。display的值是inline-block、table-cell、flex、table-caption或者inline-flex。BFC的作用利用BFC避免margin重叠自适应两栏布局清除浮动三、DOM事件3.1 事件级别三个事件级别注意没有 DOM1因为 DOM1 标准制定的时候没有涉及 DOM事件。DOM3 比 DOM2 只是增加了一些事件类型。DOM0element.onclick function(){}DOM2element.addEventListener(click, function(){}, false)DOM3element.addEventListener(keyup, function(){}, false)### 3.2 事件模型和事件流 DOM事件模型包括捕获和冒泡。事件流即用户与界面交互的过程中事件的流向过程。3.3 DOM事件捕获的具体流程捕获的流程为window - document - html - body - ... - 目标元素。冒泡的流程为目标元素 - ... - body - html - document - window。3.4 Event 对象常见应用event. preventDefault()取消事件的默认动作。event.stopPropagation()阻止事件冒泡。event.stopImmediatePropagation()阻止剩下的事件处理程序被执行。如果一个元素上绑定了三个事件在其中一个事件上调用了这个方法那其他 的两个事件将不会被执行。3.5 事件捕获流程和自定义事件示例!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitledom事件/titlelink relstylesheet href /head bodystyle typetext/css mediascreen#wrapper {width: 300px;height: 150px;background: yellow;}/stylediv idwrapper点我啊点我啊/divscript typetext/javascriptvar eve document.getElementById(wrapper);//验证事件捕获过程window.addEventListener(click, function(){console.log(window capture)}, true)document.addEventListener(click, function(){console.log(document capture)}, true) //document.documentElement 获取的是 html 标签document.documentElement.addEventListener(click, function(){console.log(html capture)}, true)document.body.addEventListener(click, function(){console.log(body capture)}, true)eve.addEventListener(click, function(){console.log(eve capture)}, true)//自定义事件var customEvent new Event(test)eve.addEventListener(test, function(){console.log(自定义事件 test 触发)}, true)setTimeout(() {eve.dispatchEvent(customEvent)}, 3000)/script /body /html 复制代码控制台打印的结果为window capture document capture html capture body capture eve capture 复制代码证明了事件捕获的流程为window - document - html - body - ... - 目标元素。自定义事件设定了 3秒后触发刷新页面3秒后控制台打印出 自定义事件 test 触发 。四、HTTP协议4.1 http协议的主要特点简单快速、灵活、无连接、无状态HTTP三点注意事项HTTP是无连接无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求并收到客户的应答后即断开连接。采用这种方式可以节省传输时间。HTTP是媒体独立的这意味着只要客户端和服务器知道如何处理的数据内容任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。HTTP是无状态HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息则它必须重传这样可能导致每次连接传送的数据量增大。另一方面在服务器不需要先前信息时它的应答就较快。4.2 请求报文一个HTTP请求报文由请求行request line、请求头header、空行和请求数据4个部分组成下图给出了请求报文的一般格式。请求行 包括请求方法字段、URL字段和HTTP协议版本如GET /index.html HTTP/1.1。请求头请求头部由关键字/值对组成每行一对关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息典型的请求头有User-Agent产生请求的浏览器类型。Accept客户端可识别的内容类型列表。Host请求的主机名允许多个域名同处一个IP地址即虚拟主机。Content-Type请求体的MIME类型 用于POST和PUT请求中。如Content-Type: application/x-www-form-urlencoded空行最后一个请求头之后是一个空行发送回车符和换行符通知服务器以下不再有请求头。请求数据请求数据不在GET方法中使用而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。4.3 响应报文包括状态行、响应头、空行、响应正文。4.4 HTTP 状态码HTTP状态码的英文为HTTP Status Code。状态代码由三位数字组成第一个数字定义了响应的类别且有五种可能取值。1xx指示信息--表示请求已接收继续处理。2xx成功--表示请求已被成功接收、理解、接受。3xx重定向--要完成请求必须进行更进一步的操作。4xx客户端错误--请求有语法错误或请求无法实现。5xx服务器端错误--服务器未能实现合法的请求。常见状态代码、状态描述的说明如下。200 OK客户端请求成功。400 Bad Request客户端请求有语法错误不能被服务器所理解。401 Unauthorized请求未经授权这个状态代码必须和WWW-Authenticate报头域一起使用。403 Forbidden服务器收到请求但是拒绝提供服务。404 Not Found请求资源不存在举个例子输入了错误的URL。500 Internal Server Error服务器发生不可预期的错误。503 Server Unavailable服务器当前不能处理客户端的请求一段时间后可能恢复正常举个例子HTTP/1.1 200 OKCRLF。4.5 优化DNS 预解析!--在head标签中越早越好-- link reldns-prefetch href//example.com 复制代码HTTP预连接link relpreconnect href//example.com link relpreconnect href//cdn.example.com crossorigin 复制代码4.6 浏览器输入 url 之后发生了什么网上有很多答案也没有一个统一的标准答案多看几个把大概流程说出来即可。五、原型链5.1 创建对象的几种方法!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitle原型链/titlelink relstylesheet href /head bodyscript typetext/javascript charsetutf-8//创建对象的几种方式//1.字面量var obj1 {name: solo obj1};//2.new Objectvar obj2 new Object({name: solo obj2})//3.构造函数创建var M function(name){this.name name;}var obj3 new M(solo obj3);//4.Object.createvar p {name: p};var obj4 Object.create(p);/script /body /html 复制代码然后在控制台查看各对象的值5.2 原型、构造函数、实例、原型链构造函数、原型对象、实例的关系可以参照下图结合上一节控制台的打印值可以得出结论构造函数.prototype.constructor 构造函数M.prototype.constructor M 的结果为 true构造函数.prototype 实例对象. protoM.prototype obj3._ proto _ 的结果为 true5.3 instanceof 的原理instanceof 用于判断一个引用类型是否属于某构造函数还可以在继承关系中用来判断一个实例是否属于它的父类型。instanceof 的原理是判断实例对象的 __proto__ 是否与构造函数的 prototype 指向同一个引用。只要在实例对象的原型链上的构造函数instaceof 都会返回 true。看下图obj3 是 M 的实例所以 obj3 instanceof M true ;同时 obj3 instanceof Object的结果也是 true因为obj3.__proto__ M.prototype true M.prototype.__proto__ Object.prototype true 复制代码如果想准确的判断构造函数究竟是哪个可以用 constructorobj3.__proto__.constructor M trueobj3.__proto__.constructor Object false 复制代码5.4 instanceof 和 typeof 的区别typeof 对于基本数据类型null, undefined, string, number, boolean, symbol除了 null 都会返回正确的类型。null 会返回 object。typeof 对于对象类型除了函数会返回 function其他的都返回 object。如果我们想获得一个变量的正确类型可以通过 Object.prototype.toString.call(xx) 。这样我们就可以获得类似 [object Type] 的字符串。判断是否等于 undefined 的方法let a // 我们也可以这样判断 undefined a undefined // 但是 undefined 不是保留字能够在低版本浏览器被赋值 let undefined 1 // 这样判断就会出错 // 所以可以用下面的方式来判断并且代码量更少 // 因为 void 后面随便跟上一个组成表达式 // 返回就是 undefined a void 0 复制代码5.5 new运算符用代码实现一个 new 方法!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitle模拟new的过程/titlelink relstylesheet href /head bodyscript typetext/javascript charsetutf-8 async deferfunction Person(name, age){this.name name;this.age age;}//手动实现newfunction _new(){//1.拿到传入的参数中的第一个参数即构造函数名Funcvar Func [].shift.call(arguments)//2.创建一个空对象obj,并让其继承Func.prototypevar obj Object.create(Func.prototype)//第二步也可以这样写// var obj {}// obj.__proto__ Func.prototype//3.执行构造函数并将this指向创建的空对象objvar ret Func.apply(obj, arguments)//4.如果构造函数返回的值是对象则返回不是对象则返回创建的对象objreturn typeof ret object ? ret : obj}var p1 _new(Person, bob, 19)console.log(p1)/script /body /html 复制代码如何理解 [].shift.call(arguments)因为 shift 内部实现是使用的this代表调用对象。那么当[].shift.call() 传入 arguments对象的时候通过 call函数改变原来 shift 方法的 this 指向, 使其指向 arguments并对 arguments 进行复制操作而后返回一个新数组。至此便是完成了 arguments 类数组转为数组的目的其实这可以理解为让类数组调用数组的方法六、面向对象6.1 类的声明和实例化声明类有两种方法function Animal(name){this.name name; }class Animal2 {constructor(name){this.name name;} } 复制代码类的实例化只有一种方式var a1 new Animal(shape); var a2 new Animal2(cat); 复制代码6.2 继承继承有多种实现方式6.2.1 借助构造函数实现继承先看代码Parent1 是父类Child1 是子类。通过 Parent1.call(this, name) 改变了 this 指向使子类继承了父类的属性即 Child1 也有了 name 属性。/*构造函数实现继承 */ function Parent1(name){this.name name; }function Child1(name, age){Parent1.call(this, name)this.age age }var c1 new Child1(bobo, 19) console.log(c1) 复制代码运行程序打印结果但是 这种方式不能继承父类原型链上的属性只能继承在父类显式声明的属性 。看下面的代码通过Parent1.prototype.say给 Parent1 新增一个 say 方法那么 Child1 能不能也继承呢function Parent1(name){this.name name; }Parent1.prototype.say function(){console.log(say hello) }function Child1(name, age){Parent1.call(this, name)this.age age }var p1 new Parent1(hehe) var c1 new Child1(bobo, 19) console.log(p1) console.log(c1) 复制代码输出结果如下Parent1 中有 say 方法而 Child1 中没有说明没有继承到。6.2.2 借助原型链实现继承实现原理是将 Child.prototype 赋值为一个新的 Parent 对象即 Child2.prototype new Parent2(bob)function Parent2(name){this.name name;this.arr [1,2,3] }function Child2(age){this.age age }//重点在这句 Child2.prototype new Parent2(bob)c2 new Child2(20) c3 new Child2(22) console.log(c2, c2) console.log(c3, c3) 复制代码控制台输出如下这种方法也有缺点看 arr 属性是一个数组如果创建两个实例对象 c2、c3因为这两个实例对象的 arr 指向同一个引用所以改变其中一个的值另一个也会跟着改变。我们来看下面的实验c2.arr 和 c3.arr 值都是 [1,2,3]此时通过 c2.arr.push(4) 给 c2.arr 添加一个元素c2.arr 变成了 [1,2,3,4]这没有问题。但再看 c3.arr 也是 [1,2,3,4]这就有问题了不是我们期望的。6.2.3 组合方式实现继承以上两种方式单独使用都有一定局限性把两种方式结合起来是不是完美了呢/*** 组合模式*/ function Parent3(name){this.name name;this.arr [1,2,3] } function Child3(name, age){Parent3.call(this, name)this.age age } Child3.prototype new Parent3()Parent4.prototype.say function(){console.log(say hi) }var c4 new Child3(ciri, 16) var c5 new Child3(heha, 32) 复制代码再在控制台做实验通过结果可以看到子类 Child3 继承了父类原型链上的属性一个实例改变 arr 的值不会影响到另一个。解决了前两种的缺陷。但是 在实例化 Child3 的时候父类 Parent3 的构造函数被执行了两遍这是没必要的。为什么执行了两遍父类构造函数因为 new Child3(ciri, 16) 的时候子类构造函数中 Parent3.call(this, name) 执行了一次父类构造函数然后 Child3.prototype new Parent3() 又有一个 new Parent() 第二次执行了父类构造函数。所以还可以再优化。6.2.4 组合方式优化1上面说到了执行了两次父类构造函数其中第二次是 Child3.prototype new Parent3() 那么把 new Parent3() 换掉不就可以了是的根据上一章原型链的知识可以替换为 Child3.prototype Parent3.prototype//组合方式优化1 function Parent4(name){this.name name;this.arr [1,2,3] }function Child4(name, age){//重点1Parent4.call(this, name)this.age age } //重点2 Child4.prototype Parent4.prototypeParent4.prototype.say function(){console.log(say hi) }var c6 new Child4(ciri, 16) var c7 new Child4(heha, 32)console.log(c6 instanceof Child4, c6 instanceof Parent4) console.log(c6.constructor) 复制代码以上就是组合方式优化1解决了执行两遍父类构造函数的问题。这种方式就完美了吗NO看最后打印的两行 c6 instanceof Child4 和 c6 instanceof Parent4 都为 true这没问题。但是 c6.constructor 是谁呢正常来说应该是 Child4那么看一下打印结果却是 Parent4。**为什么有这种现象呢再看一下这张图Parent4.prototype.constructor 其实是指向了 Parent4 自己因为 Child4.prototype Parent4.prototype 共用了一个原型对象所以 Child4.prototype.constructor 当然也是 Parent4 了。那用 6.2.3 中 Child3.prototype new Parent3() 这种方式有没有这个问题呢一样的因为 Child3 没有 constructor它的 constructor 是从 new Parent3() 继承的所以也是 Parent3。6.2.5 组合方式优化2直接看最完美的继承写法//组合方式优化2 function Parent5(name){this.name name } function Child5(name, age){Parent5.call(this, name)this.age age } Child5.prototype Object.create(Parent5.prototype) Child5.prototype.constructor Child5var c8 new Child5() console.log(c8 instanceof Child5, c8 instanceof Parent5) console.log(c8.constructor) 复制代码与上一种方法的区别是Child5.prototype Object.create(Parent5.prototype) Child5.prototype.constructor Child5 复制代码** Object.create() **方法创建一个新对象使用现有的对象来提供新创建的对象的__proto__。即返回一个带着指定的原型对象和属性的新对象。Child5.prototype 和 Parent5.prototype 不再使用同一个引用中间用一个新的对象隔离开了。此时 Child5 还没有 constructor所以要手动指定一个 Child5.prototype.constructor Child5至此继承的完美解决方案诞生了。那么可不可以在 6.2.4 中 Child4.prototype Parent4.prototype 下面直接写个 Child4.prototype.constructor Child4 呢不可以因为它们指向的是同一个对象改变了 Child4 的 constructorParent4 的 constructor 也变成了 Child4。七、通信类7.1 同源策略及限制同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。协议、域名、端口只要有一个不一样就是不同的源。不同源的限制Cookie、LocalStorage、IndexDB 无法获取DOM 无法获取Ajax 请求不能发送(Ajax 只限于同源使用不能跨域使用)7.2 前后端如何通信AjaxWebSocketCORS7.3 跨域通信的几种方式JSONP(利用 script 标签的异步加载实现的)Hashwindow.location.hash iframepostMessage (H5中新增的)WebSocketCORS参考文章 segmentfault.com/a/119000001…八、安全类前端安全分两类CSRF、XSS常考点基本概念和缩写、攻击原理、防御措施8.1 CSRFCSRFCross-site request forgery跨站请求伪造。攻击原理用户C打开浏览器访问受信任网站A输入用户名和密码请求登录网站A在用户信息通过验证后网站A产生Cookie信息并返回给浏览器此时用户登录网站A成功可以正常发送请求到网站A用户未退出网站A之前在同一浏览器中打开一个TAB页访问网站B网站B接收到用户请求后返回一些攻击性代码并发出一个请求要求访问第三方站点A浏览器在接收到这些攻击性代码后根据网站B的请求在用户不知情的情况下携带Cookie信息向网站A发出请求。网站A并不知道该请求其实是由B发起的所以会根据用户C的Cookie信息以C的权限处理该请求导致来自网站B的恶意代码被执行。防御措施Token验证Referer 验证简单易行但 referer 可能被改变隐藏令牌跟 Token验证差不多把令牌存到 header 中8.2 XSSXSScross-site scripting跨域脚本攻击攻击原理往 Web 页面里插入恶意Script代码防御措施HTML对以下这些字符进行转义 alt;// 复制代码Javascript把所有非字母、数字的字符都转义成小于256的ASCII字符URL使用Javascript的encodeURIComponent()方法对用户的输入进行编码该方法会编码如下字符, / ? : $ #九、算法算法前端问的不太多建议先复习其他的有精力了再复习算法。排序排序算法比较多重点掌握快速排序、选择排序、希尔排序、冒泡排序这四种即可。术语稳定 如果a原本在b前面而ab排序之后a仍然在b的前面 不稳定 如果a原本在b的前面而ab排序之后a可能会出现在b的后面 内排序 所有排序操作都在内存中完成 外排序 由于数据太大因此把数据放在磁盘中而排序通过磁盘和内存的数据传输才能进行 时间复杂度 一个算法执行所耗费的时间。 空间复杂度 运行完一个程序所需内存的大小。各种算法的时间复杂度冒泡排序冒泡排序 是一种简单的排序算法。它重复地走访过要排序的数列一次比较两个元素如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。时间复杂度最佳情况T(n) O(n)最差情况T(n) O(n^2)平均情况T(n) O(n^2)//冒泡排序 function bubbleSort(arr){if(!arr || arr.length 0){return;}for(let i0; iarr.length; i){for(let j0; ji; j){if (arr[i] arr[j]) {//交换两个元素的位置[arr[i], arr[j]] [arr[j], arr[i]]}}}return arr; }let arr [2,5,1,8,19,3,32]; console.log(排序前: , arr) console.log(冒泡排序后: , bubbleSort(arr));//输出 排序前: [2, 5, 1, 8, 19, 3, 32] 冒泡排序后: [1, 2, 3, 5, 8, 19, 32] 复制代码选择排序选择排序(Selection-sort) 是一种简单直观的排序算法。它的工作原理首先在未排序序列中找到最小大元素存放到排序序列的起始位置然后再从剩余未排序元素中继续寻找最小大元素然后放到已排序序列的末尾。以此类推直到所有元素均排序完毕。时间复杂度最佳情况T(n) O(n^2)最差情况T(n) O(n^2)平均情况T(n) O(n^2)function selectSort(arr){if(!arr || arr.length 0){return arr;}for(let i0; iarr.length; i){let minIndex i;for(let ji; jarr.length; j){//找出最小元素的下标if(arr[j] arr[i]){minIndex j;}}//交换两个元素的位置[arr[i], arr[minIndex]] [arr[minIndex], arr[i]]}return arr; } 复制代码堆栈、队列、列表待完善…递归待完善…波兰式和逆波兰式待完善…十、渲染机制10.1 DOCTYPE 及其作用DTD (Document type definition文档类型定义) 是一系列的语法规则用来定义 XML 或 HTML 的文件类型。浏览器会使用它来判断文档类型决定使用何种协议来解析以及切换浏览器模式。DOCTYPE 是用来声明文档类型和 DTD 规范的一个主要的用途便是文件的合法性验证。如果文件代码不合法那么浏览器解析时便会出一些差错。注意!DOCTYPE 声明不区分大小写。HTML5!DOCTYPE html 复制代码HTML 4.01 Strict这个 DTD 包含所有 HTML 元素和属性但不包括表象或过时的元素如 font 。框架集是不允许的。!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01//EN http://www.w3.org/TR/html4/strict.dtd 复制代码HTML 4.01 Transitional这个 DTD 包含所有 HTML 元素和属性包括表象或过时的元素如 font 。框架集是不允许的。!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd 复制代码HTML 4.01 Frameset这个 DTD 与 HTML 4.01 Transitional 相同但是允许使用框架集内容。!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Frameset//EN http://www.w3.org/TR/html4/frameset.dtd 复制代码10.2 浏览器渲染过程这个问题照着这张图讲清楚就好。浏览器拿到 HTML 和 CSS 之后通过 HTML Parser 把 HTML 解析成 DOM Tree , 通过 CSS Parser 把 CSS 解析成 Style Rules 即 CSS 规则然后 DOM Tree 和 CSS规则 结合起来形成 Render Tree 。然后进行布局 Layout 和绘制 Painting最终 Display 显示在页面上。10.3 重排 Reflow定义DOM 结构中各个元素都有自己的盒子模型这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置这个过程称为 reflow。触发 Reflow什么情况会触发 Reflow 呢记住两三个就可以增加、删除、修改 DOM 节点时会导致 Reflow 或 Repaint移动 DOM 位置或搞个动画时修改 CSS 样式时Resize 窗口移动端没这个问题或滚动的时候修改网页默认字体时10.4 重绘 Repaint定义当各种盒子的位置、大小以及其他属性例如颜色、字体大小等都确定之后浏览器把这些元素按照各自的特性绘制了一遍于是页面内容出现了这个过程称之为 repaint。触发 RepaintDOM 改动CSS 改动如何最小程度的 Repaint比如要添加多个 DOM 节点一次性添加而不要一个个添加。10.5 dispaly:none 和 visibility:hiddendispaly:none 设置该属性后该元素下的元素都会隐藏占据的空间消失。visibility:hidden 设置该元素后元素虽然不可见了但是依然占据空间的位置。display:none和visibility:hidden的区别1.visibility具有继承性其子元素也会继承此属性若设置visibility:visible则子元素会显示2.visibility不会影响计数器的计算虽然隐藏掉了但是计数器依然继续运行着。3.在css3的transition中支持visibility属性但是不支持display因为transition可以延迟执行因此配合visibility使用纯css实现hover延时显示效果可以提高用户体验4. display:none会引起回流(重排)和重绘 visibility:hidden会引起重绘十一、JS运行机制掌握下面几个要点理解 JS 的单线程概念理解任务队列理解 EventLoop理解哪些语句会放入异步任务队列理解语句放入异步任务队列的时机11.1 为什么 JavaScript 是单线程JavaScript语言的一大特点就是单线程也就是说同一个时间只能做一件事。那么为什么JavaScript不能有多个线程呢这样能提高效率啊。JavaScript的单线程与它的用途有关。作为浏览器脚本语言JavaScript的主要用途是与用户互动以及操作DOM。这决定了它只能是单线程否则会带来很复杂的同步问题。比如假定JavaScript同时有两个线程一个线程在某个DOM节点上添加内容另一个线程删除了这个节点这时浏览器应该以哪个线程为准所以为了避免复杂性从一诞生JavaScript就是单线程这已经成了这门语言的核心特征将来也不会改变。为了利用多核CPU的计算能力HTML5提出Web Worker标准允许JavaScript脚本创建多个线程但是子线程完全受主线程控制且不得操作DOM。所以这个新标准并没有改变JavaScript单线程的本质。11.2 任务队列单线程就意味着所有任务需要排队前一个任务结束才会执行后一个任务。如果前一个任务耗时很长后一个任务就不得不一直等着。所有任务可以分成两种一种是 同步任务 synchronous另一种是 异步任务 asynchronous。同步任务指的是在主线程上排队执行的任务只有前一个任务执行完毕才能执行后一个任务异步任务指的是不进入主线程、而进入任务队列task queue的任务只有任务队列通知主线程某个异步任务可以执行了该任务才会进入主线程执行。具体来说异步执行的运行机制如下:同步执行也是如此因为它可以被视为没有异步任务的异步执行。1所有同步任务都在主线程上执行形成一个执行栈execution context stack。 2主线程之外还存在一个任务队列task queue。只要异步任务有了运行结果就在任务队列之中放置一个事件。 3一旦执行栈中的所有同步任务执行完毕系统就会读取任务队列看看里面有哪些事件。那些对应的异步任务于是结束等待状态进入执行栈开始执行。 4主线程不断重复上面的第三步。 复制代码只要主线程空了就会去读取任务队列这就是JavaScript的运行机制。这个过程会不断重复。11.3 宏任务 微任务这里需要注意的是new Promise是会进入到主线程中立刻执行而promise.then则属于微任务宏任务(macro-task)整体代码script、setTimeOut、setInterval微任务(mincro-task)promise.then、promise.nextTick(node)11.4 EventLoop 事件循环主线程从任务队列中读取事件这个过程是循环不断的所以整个的这种运行机制又称为Event Loop事件循环。整体的script(作为第一个宏任务)开始执行的时候会把所有代码分为两部分“同步任务”、“异步任务”同步任务会直接进入主线程依次执行异步任务会再分为宏任务和微任务宏任务进入到Event Table中并在里面注册回调函数每当指定的事件完成时Event Table会将这个函数移到Event Queue中微任务也会进入到另一个Event Table中并在里面注册回调函数每当指定的事件完成时Event Table会将这个函数移到Event Queue中当主线程内的任务执行完毕主线程为空时会检查微任务的Event Queue如果有任务就全部执行如果没有就执行下一个宏任务上述过程会不断重复这就是Event Loop事件循环11.5 定时器除了放置异步任务的事件任务队列还可以放置定时事件即指定某些代码在多少时间之后执行。这叫做定时器timer功能也就是定时执行的代码。定时器功能主要由setTimeout()和setInterval()这两个函数来完成它们的内部运行机制完全一样区别在于前者指定的代码是一次性执行后者则为反复执行。以下主要讨论setTimeout()。setTimeout()接受两个参数第一个是回调函数第二个是推迟执行的毫秒数。console.log(1); setTimeout(function(){console.log(2);},1000); console.log(3); 复制代码上面代码的执行结果是132因为setTimeout()将第二行推迟到1000毫秒之后执行。如果将setTimeout()的第二个参数设为0就表示当前代码执行完执行栈清空以后立即执行0毫秒间隔指定的回调函数。setTimeout(function(){console.log(1);}, 0); console.log(2); 复制代码上面代码的执行结果总是21因为只有在执行完第二行以后系统才会去执行任务队列中的回调函数。总之setTimeout(fn,0)的含义是指定某个任务在主线程最早可得的空闲时间执行也就是说尽可能早得执行。它在任务队列的尾部添加一个事件因此要等到同步任务和任务队列现有的事件都处理完才会得到执行。HTML5标准规定了setTimeout()的第二个参数的最小值最短间隔不得低于 4毫秒 如果低于这个值就会自动增加。在此之前老版本的浏览器都将最短间隔设为10毫秒。另外对于那些DOM的变动尤其是涉及页面重新渲染的部分通常不会立即执行而是 每16毫秒执行一次 。这时使用requestAnimationFrame()的效果要好于setTimeout()。需要注意的是setTimeout()只是将事件插入了任务队列必须等到当前代码执行栈执行完主线程才会去执行它指定的回调函数。要是当前代码耗时很长有可能要等很久所以并没有办法保证回调函数一定会在setTimeout()指定的时间执行。11.6 哪些是异步任务setTimeout 和 setIntervalDOM 事件Promise网络请求I/O11.7 常考题1) 第一题下面代码的输出结果是什么console.log(1); setTimeout(function(){console.log(2) }, 0); console.log(3) 复制代码答案132解析 console.log() 是同步任务 setTimeout 是异步任务。异步任务会等同步任务执行完再执行。虽然 setTimeout 设置的延迟是 0但浏览器规定延迟最小为 4ms所以 console.log(2) 在 4ms 后被放入任务队列。当同步任务执行完即打印完 13 之后主线程再从任务队列中取任务打印 2。2) 第二题下面的代码输出结果是什么console.log(A) while(true){} console.log(B) 复制代码答案A解析代码从上往下执行先打印 A然后 while 循环因为条件一直是 true所以会进入死循环。while 不执行完就不会执行到第三行。这个题目还有个变种console.log(A); setTimeout(function(){console.log(B) }, 0); while(1){} 复制代码同样只会输出 A。因为异步任务需要等同步任务执行完之后才执行while 进入了死循环所以不会打印 B。3) 第三题下面代码输出结果for(var i0; i4; i){setTimeout(function(){console.log(i)}, 0) } 复制代码结果4个4。解析这题主要考察异步任务放入任务队列的时机。当执行到 setTimeout 即定时器时并不会马上把这个异步任务放入任务队列而是等时间到了之后才放入。然后等执行栈中的同步任务执行完毕后再从任务队列中依次取出任务执行。for 循环是同步任务会先执行完循环此时 i 的值是 4。4ms后 console.log(i) 被依次放入任务队列此时如果执行栈中没有同步任务了就从任务队列中依次取出任务所以打印出 4 个 4。那么如何才能按照期望打印出 0, 123 呢有三个方法//方法1把 var 换成 let for(let i0; i4; i){setTimeout(function(){console.log(i)}, 0) }//方法2使用立即执行函数 for(let i0; i4; i){(function(i){setTimeout(function(){console.log(i)}, 0)})(i) }//方法3加闭包 for(let i0; i4; i){var a function(){var j i;setTimeout(function(){console.log(j)}, 0)}a(); } 复制代码4) 第四题setTimeout(function(){console.log(1) }); new Promise(function(resolve){console.log(2);for(var i 0; i 10000; i){i 9999 resolve();} }).then(function(){console.log(3) }); console.log(4); 执行结果 // 2 4 3 1 复制代码分析1.setTimeout是异步且是宏函数放到宏函数队列中2.new Promise是同步任务直接执行打印2并执行for循环3.promise.then是微任务放到微任务队列中4.console.log(4)同步任务直接执行打印45.此时主线程任务执行完毕检查微任务队列中有promise.then执行微任务打印36.微任务执行完毕第一次循环结束从宏任务队列中取出第一个宏任务到主线程执行打印17.结果24315) 第五题console.log(1);setTimeout(function() {console.log(2); }, 0);Promise.resolve().then(function() {console.log(3); }).then(function() {console.log(4.我是新增的微任务); });console.log(5);执行结果 // 1534.我是新增的微任务2 复制代码分析1.console.log(1)是同步任务直接执行打印12.setTimeout是异步且是宏函数放到宏函数队列中3.Promise.resolve().then是微任务放到微任务队列中4.console.log(5)是同步任务直接执行打印55.此时主线程任务执行完毕检查微任务队列中有Promise.resolve().then执行微任务打印36.此时发现第二个.then任务属于微任务添加到微任务队列并执行打印4.我是新增的微任务7.这里强调一下微任务执行过程中发现新的微任务会把这个新的微任务添加到队列中微任务队列依次执行完毕后才会执行下一个循环8.微任务执行完毕第一次循环结束取出宏任务队列中的第一个宏任务setTimeout到主线程执行打印29.结果1534.我是新增的微任务26) 第六题function add(x, y) {console.log(1)setTimeout(function() { // timer1console.log(2)}, 1000) } add();setTimeout(function() { // timer2console.log(3) })new Promise(function(resolve) {console.log(4)setTimeout(function() { // timer3console.log(5)}, 100)for(var i 0; i 100; i) {i 99 resolve()} }).then(function() {setTimeout(function() { // timer4console.log(6) }, 0)console.log(7) })console.log(8)执行结果 //14873652 复制代码分析1.add()是同步任务直接执行打印12.add()里面的setTimeout是异步任务且宏函数记做timer1放到宏函数队列3.add()下面的setTimeout是异步任务且宏函数记做timer2放到宏函数队列4.new Promise是同步任务直接执行打印45.Promise里面的setTimeout是异步任务且宏函数记做timer3放到宏函数队列6.Promise里面的for循环同步任务执行代码7.Promise.then是微任务放到微任务队列8.console.log(8)是同步任务直接执行打印89.此时主线程任务执行完毕检查微任务队列中有Promise.then执行微任务发现有setTimeout是异步任务且宏函数记做timer4放到宏函数队列10.微任务队列中的console.log(7)是同步任务直接执行打印711.微任务执行完毕第一次循环结束12.检查宏任务Event Table里面有timer1、timer2、timer3、timer4四个定时器宏任务按照定时器延迟时间得到可以执行的顺序即Event Queuetimer2、timer4、timer3、timer1取出排在第一个的timer213.取出timer2执行console.log(3)同步任务直接执行打印314.没有微任务第二次Event Loop结束15.取出timer4执行console.log(6)同步任务直接执行打印616.没有微任务第三次Event Loop结束17.取出timer3执行console.log(5)同步任务直接执行打印518.没有微任务第四次Event Loop结束19.取出timer1执行console.log(2)同步任务直接执行打印220.没有微任务也没有宏任务第五次Event Loop结束21.结果148736527) 第七题setTimeout(function() { // timer1console.log(1);setTimeout(function() { // timer3console.log(2);}) }, 0); setTimeout(function() { // timer2console.log(3); }, 0);执行结果 //132 复制代码分析1.第一个setTimeout是异步任务且宏函数记做timer1放到宏函数队列2.第三个setTimeout是异步任务且宏函数记做timer2放到宏函数队列3.没有微任务第一次Event Loop结束4.取出timer1console.log(1)同步任务直接执行打印15.timer1里面的setTimeout是异步任务且宏函数记做timer3放到宏函数队列6.没有微任务第二次Event Loop结束7.取出timer2console.log(3)同步任务直接执行打印38.没有微任务第三次Event Loop结束9.取出timer3console.log(2)同步任务直接执行打印210.没有微任务也没有宏任务第四次Event Loop结束11.结果132十二、页面性能面试必考这五个最好都能记住。异步加载和浏览器缓存都会延伸了问其他三个只要说出来即可。提升页面性能的方法有哪些资源压缩合并减少 HTTP 请求非核心代码异步加载异步加载的方式异步加载的区别利用浏览器缓存缓存的分类缓存原理使用 CDN预解析 DNS//强制打开 a 标签的 dns 解析 meta http-equivx-dns-prefetch-controller contenton //DNS预解析 link reldns-prefetch href//host_name_to_prefetch.com 复制代码12.1 异步加载异步加载的方式动态脚本加载deferasync异步加载的区别defer 是在 HTML 解析完之后才会执行如果是多个按照加载的顺序依次执行。 defer 脚本会在 DOMContentLoaded 和 load 事件之前执行。async 是在脚本加载完之后立即执行如果是多个执行顺序和加载顺序无关。 async 会在 load 事件之前执行但并不能确保与 DOMContentLoaded 的执行先后顺序。下面两张图可以更清楚地阐述 defer 和 async 的执行以及和 DOMContentLoaded 、 load 事件的关系12.2 浏览器缓存缓存策略的分类强缓存协商缓存缓存策略都是通过设置 HTTP Header 来实现的。浏览器每次发起请求都会先在浏览器缓存中查找该请求的结果以及缓存标识。浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中。12.2.1 强缓存强缓存不会向服务器发送请求直接从缓存中读取资源在chrome控制台的Network选项中可以看到该请求返回200的状态码并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现Expires 和 Cache-Control。1. Expires缓存过期时间用来指定资源到期的时间是服务器端的具体的时间点。也就是说Expiresmax-age 请求时间需要和Last-modified结合使用。Expires是Web服务器响应消息头字段在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据而无需再次请求。Expires 是 HTTP/1 的产物受限于本地时间如果修改了本地时间可能会造成缓存失效。 Expires: Wed, 22 Oct 2018 08:41:00 GMT 表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期需要再次请求。2. Cache-Control在HTTP/1.1中Cache-Control是最重要的规则主要用于控制网页缓存。比如当 Cache-Control:max-age300 时则代表在这个请求正确返回时间浏览器也会记录下来的5分钟内再次加载资源就会命中强缓存。Cache-Control 可以在请求头或者响应头中设置并且可以组合使用多种指令3. Expires和Cache-Control两者对比其实这两者差别不大区别就在于 Expires 是http1.0的产物Cache-Control是http1.1的产物两者同时存在的话Cache-Control优先级高于Expires 在某些不支持HTTP1.1的环境下Expires就会发挥用处。所以Expires其实是过时的产物现阶段它的存在只是一种兼容性的写法。强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段而不关心服务器端文件是否已经更新这可能会导致加载文件不是服务器端最新的内容那我们如何获知服务器端内容是否已经发生了更新呢此时我们需要用到协商缓存策略。12.2.2 协商缓存协商缓存就是强制缓存失效后浏览器携带缓存标识向服务器发起请求由服务器根据缓存标识决定是否使用缓存的过程主要有以下两种情况协商缓存生效返回304和Not Modified协商缓存失效返回200和请求结果协商缓存可以通过设置两种 HTTP Header 实现Last-Modified 和 ETag 。1. Last-Modified 和 If-Modified-Since浏览器在第一次访问资源时服务器返回资源的同时在response header中添加 Last-Modified 的header值是这个资源在服务器上的最后修改时间浏览器接收后缓存文件和 headerLast-Modified: Fri, 22 Jul 2016 01:47:00 GMT 复制代码浏览器下一次请求这个资源浏览器检测到有 Last-Modified这个header于是添加If-Modified-Since这个header值就是Last-Modified中的值服务器再次收到这个资源请求会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比如果没有变化返回304和空的响应体直接从缓存读取如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间说明文件有更新于是返回新的资源文件和200。但是 Last-Modified 存在一些弊端如果本地打开缓存文件即使没有对文件进行修改但还是会造成 Last-Modified 被修改服务端不能命中缓存导致发送相同的资源因为 Last-Modified 只能以秒计时如果在不可感知的时间内修改完成文件那么服务端会认为资源还是命中了不会返回正确的资源既然根据文件修改时间来决定是否缓存尚有不足能否可以直接根据文件内容是否修改来决定缓存策略所以在 HTTP / 1.1 出现了 ETag 和 If-None-Match2. ETag 和 If-None-MatchEtag 是服务器响应请求时返回当前资源文件的一个唯一标识(由服务器生成)只要资源有变化Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时会将上一次返回的Etag值放到request header里的If-None-Match里服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上那么直接以常规GET 200回包形式将新的资源当然也包括了新的ETag发给客户端如果ETag是一致的则直接返回304知会客户端直接使用本地缓存即可。3. 两者之间对比首先在精确度上Etag要优于Last-Modified。Last-Modified的时间单位是秒如果某个文件在1秒内改变了多次那么他们的Last-Modified其实并没有体 现出来修改但是Etag每次都会改变确保了精度如果是负载均衡的服务器各个服务器生成的Last- Modified也有可能不一致。第二在性能上Etag要逊于Last-Modified毕竟Last-Modified只需要记录时间而Etag需要服务器通过算法来计算出一个hash值。第三在优先级上服务器校验优先考虑Etag12.2.3 缓存机制强制缓存优先于协商缓存进行若强制缓存(Expires和Cache-Control)生效则直接使用缓存若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)协商缓存由服务器决定是否使用缓存若协商缓存失效那么代表该请求的缓存失效返回200重新返回资源和缓存标识再存入浏览器缓存中生效则返回304继续使用缓存。12.2.4 强缓存与协商缓存的区别强缓存与协商缓存的区别可以用下表来表示缓存类型获取资源形式状态码发送请求到服务器强缓存从缓存取200from cache否直接从缓存取协商缓存从缓存取304Not Modified是通过服务器来告知缓存是否可用用户行为对缓存的影响用户操作Expires/Cache-ControlLast-Modied/Etag地址栏回车有效有效页面链接跳转有效有效新开窗口有效有效前进回退有效有效F5刷新无效有效CtrlF5强制刷新无效无效12.2.5 from memory cache 与 from disk cache对比在chrome浏览器中的控制台Network中size栏通常会有三种状态1.from memory cache2.from disk cache3.资源本身的大小(如1.5k)三种的区别from memory cache 字面理解是从内存中其实也是字面的含义这个资源是直接从内存中拿到的不会请求服务器一般已经加载过该资源且缓存在了内存当中当关闭该页面时此资源就被内存释放掉了再次重新打开相同页面时不会出现from memory cache的情况。from disk cache 同上类似此资源是从磁盘当中取出的也是在已经在之前的某个时间加载过该资源不会请求服务器但是此资源不会随着该页面的关闭而释放掉因为是存在硬盘当中的下次打开仍会from disk cache资源本身大小数值 当http状态为200是实实在在从浏览器获取的资源当http状态为304时该数字是与服务端通信报文的大小并不是该资源本身的大小该资源是从本地获取的状态类型说明200form memory cache不请求网络资源资源在内存当中一般脚本、字体、图片会存在内存当中。200form disk ceche不请求网络资源在磁盘当中一般非脚本会存在内存当中如css等。200资源大小数值资源大小数值 从服务器下载最新资源。304报文大小请求服务端发现资源没有更新使用本地资源即命中协商缓存。十三、错误监控13.1 前端错误分类前端错误分为两大类即时运行错误代码错误资源加载错误13.2 错误的捕获方式即时运行错误的捕获方式try...catchwindow.onerror资源加载错误捕获object.onerrorperformance.getEntries()Error 事件捕获window.onerror 只能捕获即时运行错误不能捕获资源加载错误因为资源加载错误不会冒泡。资源加载错误可以通过捕获 Error 来拿到代码演示!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitle错误监控/titlelink relstylesheet hrefscript typetext/javascriptwindow.addEventListener(error, function(e){console.log(捕获了错误, e)}, true)/script /head bodyscript src//baidu.con/test.js charsetutf-8/script /body /html 复制代码#### 跨域的 js 运行错误可以捕获到吗错误提示是什么应该怎么处理 可以捕获到错误如下![image.png](https://cdn.nlark.com/yuque/0/2020/png/252511/1581861516950-8588fc6a-1f3d-46a2-a361-034e1063baa0.png#alignleftdisplayinlineheight143margin%5Bobject%20Object%5Dnameimage.pngoriginHeight286originWidth767size111174statusdonestylenonewidth383.5)如何处理在 script 标签上增加 crossorigin 属性客户端做设置 js 资源响应头 Access-Control-Allow-Origin:*服务端做### 13.3 上报错误的基本原理采用 Ajax 通信的方式上报基本没用利用 Image 对象上报基本都用这种方式script typetext/javascript(new Image()).src http://www.baidu.com/test?thahha; /script 复制代码十四、thiscallapplybind14.1 call 和 apply 共同点都能够改变函数执行时的上下文将一个对象的方法交给另一个对象来执行并且是立即执行的。调用 call 和 apply 的对象必须是一个函数 Function14.2 call 和 apply 的区别区别主要体现在参数上。call 的写法Function.call(obj,[param1[,param2[,…[,paramN]]]]) 复制代码调用 call 的对象必须是个函数 Function。call 的第一个参数是一个对象。 Function 的调用者将会指向这个对象。如果不传则默认为全局对象 window。第二个参数开始可以接收任意个参数。每个参数会映射到相应位置的 Function 的参数上。但是如果将所有的参数作为数组传入它们会作为一个整体映射到 Function 对应的第一个参数上之后参数都为空。function func (a,b,c) {} func.call(obj, 1,2,3) // func 接收到的参数实际上是 1,2,3 func.call(obj, [1,2,3]) // func 接收到的参数实际上是 [1,2,3],undefined,undefined 复制代码apply 的写法Function.apply(obj[,argArray]) 复制代码它的调用者必须是函数 Function并且只接收两个参数第一个参数的规则与 call 一致。第二个参数必须是数组或者类数组它们会被转换成类数组传入 Function 中并且会被映射到 Function 对应的参数上。这也是 call 和 apply 之间很重要的一个区别。func.apply(obj, [1,2,3]) // func 接收到的参数实际上是 1,2,3 func.apply(obj, {0: 1,1: 2,2: 3,length: 3 }) // func 接收到的参数实际上是 1,2,3 复制代码14.3 call 和 apply 的用途下面会分别列举 call 和 apply 的一些使用场景。声明例子中没有哪个场景是必须用 call 或者必须用 apply 的只是个人习惯这么用而已。call 的使用场景1、对象的继承。如下面这个例子function superClass () {this.a 1;this.print function () {console.log(this.a);} } function subClass () {superClass.call(this);this.print(); } subClass(); // 1 复制代码subClass 通过 call 方法继承了 superClass 的 print 方法和 a 变量。此外subClass 还可以扩展自己的其他方法。2、借用方法。还记得刚才的类数组么如果它想使用 Array 原型链上的方法可以这样let domNodes Array.prototype.slice.call(document.getElementsByTagName(*)); 复制代码这样domNodes 就可以应用 Array 下的所有方法了。apply 的一些妙用1、Math.max。用它来获取数组中最大的一项。let max Math.max.apply(null, array); 复制代码同理要获取数组中最小的一项可以这样let min Math.min.apply(null, array); 复制代码2、实现两个数组合并。在 ES6 的扩展运算符出现之前我们可以用 Array.prototype.push来实现。let arr1 [1, 2, 3]; let arr2 [4, 5, 6]; Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [1, 2, 3, 4, 5, 6] 复制代码14.4 bind 的使用最后来说说 bind。在 MDN 上的解释是bind() 方法创建一个新的函数在调用时设置 this 关键字为提供的值。并在调用新函数时将给定参数列表作为原函数的参数序列的前若干项。它的语法如下Function.bind(thisArg[, arg1[, arg2[, ...]]]) 复制代码bind 方法 与 apply 和 call 比较类似也能改变函数体内的 this 指向。不同的是 bind 方法的返回值是函数并且需要稍后调用才会执行 。而 apply 和 call 则是立即调用。来看下面这个例子function add (a, b) {return a b; } function sub (a, b) {return a - b; } add.bind(sub, 5, 3); // 这时并不会返回 8 add.bind(sub, 5, 3)(); // 调用后返回 8 复制代码如果 bind 的第一个参数是 null 或者 undefinedthis 就指向全局对象 window。总结call 和 apply 的主要作用是改变对象的执行上下文并且是立即执行的。它们在参数上的写法略有区别。bind 也能改变对象的执行上下文它与 call 和 apply 不同的是返回值是一个函数并且需要稍后再调用一下才会执行。十五、防抖节流防抖触发高频函数事件后n秒内函数只能执行一次如果在n秒内这个事件再次被触发的话那么会重新计算时间。节流所谓节流就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率!DOCTYPE html html headmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitle防抖节流2/titlelink relstylesheet href /head bodyscript typetext/javascript//防抖function debounce(func, wait){let timeout;return function(){if(timeout){clearTimeout(timeout)}timeout setTimeout(() {func.apply(this, arguments)}, wait)}}//节流function throttle(func, wait){let timeout;return function(){if(!timeout){timeout setTimeout(() {timeout null;func.apply(this, arguments)}, wait)}}}function say(){console.log(hi haha)}// document.onmousemove debounce(say, 1000)document.onmousemove throttle(say, 1000)/script /body /html 复制代码还有其他感兴趣的可以看一下含光丶 - 简书
http://www.zqtcl.cn/news/713459/

相关文章:

  • 高端网站制作技术吉利汽车新能源品牌
  • 阿里云大学 网站建设常州网警
  • 做的网站访问不了lovefort表白网站制作
  • 自己如何做公司网站视频seo快速排名软件首页
  • 一站式做网站技术兰州网站设计哪个平台好
  • 网站按钮psdwordpress哪个主题
  • 阜宁网站制作哪家好建瓯建设局网站
  • 青岛网站建设团队营销网站建设的公司
  • 企业网站 dede phpcms 帝国食品网站建设建议
  • 网站建设友情链接怎样交换毕业设计网站开发的中期报告
  • 在线音乐制作网站google 网站打不开
  • 网站互联wordpress whatnew
  • 上海公司网站seo网站建设哪家公司好一点
  • 微信怎么建立自己的公众号大连网站优化技术
  • dw用ps切片做网站基金公司网站建设
  • 网站设计开户百度账号安全中心官网
  • 网站建设课程中山建网站最好的公司
  • 有没有帮忙做网站的建设银行如何招聘网站
  • 黑色网站模版网站架构图
  • 药业集团网站策划方案范文html手机网站怎么做
  • 网站虚拟主机1g南阳seo网站推广费用
  • wordpress国内视频网站吗东昌府区住房和城乡建设局网站
  • 网站免费网站的方法做网站优化词怎么选择
  • 丹东市住房和城乡建设网站seo营销型网站推广
  • 企业网站维护怎么做网站空间用万网的 域名不在万网
  • 嘉定企业网站开发建设网站建设常识网站建设技术知识大全
  • wordpress网站导航网站上如何做问卷调查
  • 南通网站搜索引擎优化海外学校网站建设
  • 个人站长适合做什么网站跨境电商数据分析网站
  • seo网站怎么优化影视制作公司简介