OSI 七层模型:
TCP/IP 四层模型:
五层模型:
HTTP请求结构:请求方式+请求URL+协议及其版本
HTTP响应结构:状态码+原因短语+协议及其版本
三次握手:
四次挥手:
Expires要求客户端和服务端的时钟严格同步。HTTP1.1引入Cache-Control来克服Expires头的限制。如果max-age和Expires同时出现,则max-age有更高的优先级。
Cache-Control:no-cache, private, max-age=0 ETag: abcde
Expires: Thu, 15 Apr 201420:00:00 GMT
Pragma: private
Last-Modified:$now //RFC1123 format
参考回答:
cache-control 是一个通用消息头字段被用于HTTP 请求和响应中,通过指定指令来实现缓存机制,这个缓存指令是单向的,常见的取值有 private、no-cache、max-age、
must-revalidate 等,默认为private。
参考回答:
XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染 DOM 树的过程成发生了不在预期内执行的 JS 代码时,就发生了 XSS 攻击。大多数XSS 攻击的主要方式是嵌入一段远程或者第三方域上的 JS 代码。实际上是在目标网站的作用域下执行了这段 JS 代码。
CSRF(Cross Site Request Forgery,跨站请求伪造),字面理解意思就是在别的站点伪造了一个请求。专业术语来说就是在受害者访问一个网站时,其 Cookie 还没有过期的情况下,攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而形成 CSRF 攻击。XSS 防御的总体思路是:对输入(和URL 参数)进行过滤,对输出进行编码。也就是对提交的所有内容进行过滤,对 url 中的参数进行过滤,过滤掉会导致脚本执行的相关内容; 然后对动态输出到页面的内容进行 html 编码,使脚本无法在浏览器中执行。虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的XSS 攻击。
防御CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。
1)我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事 件。是可以被 JavaScript 侦测到的行为。
2)事件处理机制:IE是事件冒泡、firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件。;
3)ev.stopPropagation() ;注意旧ie的方法ev.cancelBubble = true ;
调用localstorge、cookies等本地存储方式
IE支持currentStyle,FIrefox使用getComputStyle IE 使用innerText,Firefox使用textContent
滤镜方面:IE:filter:alpha(opacity= num);Firefox:-moz-opacity:num
事件方面:IE:attachEvent:火狐是addEventListener 鼠标位置:IE是event.clientX;火狐是event.pageX
IE使用event.srcElement;Firefox使用event.target
IE中消除list的原点仅需margin:0即可达到最终效果;FIrefox需要设置margin:0;padding:0以及list-
style:none
CSS圆角:ie7以下不支持圆角
Javascript数据推送
Commet:基于HTTP长连接的服务器推送技术基于WebSocket的推送方案
SSE(Server-Send Event):服务器推送数据新方式
当发送一个服务器请求时,浏览器首先会进行缓存过期判断。浏览器根据缓存过期时间判断缓存文件是 否过期。
情景一:若没有过期,则不向服务器发送请求,直接使用缓存中的结果,此时我们在浏览器控制台中可 以看到 200 OK(from cache) ,此时的情况就是完全使用缓存,浏览器和服务器没有任何交互的。
情景二:若已过期,则向服务器发送请求,此时请求中会带上①中设置的文件修改时间,和Etag
然后,进行资源更新判断。服务器根据浏览器传过来的文件修改时间,判断自浏览器上一次请求之后, 文件是不是没有被修改过;根据Etag,判断文件内容自上一次请求之后,有没有发生变化
情形一:若两种判断的结论都是文件没有被修改过,则服务器就不给浏览器发index.html的内容了,直接告诉它,文件没有被修改过,你用你那边的缓存吧—— 304 Not Modified,此时浏览器就会从本地缓存中获取index.html的内容。此时的情况叫协议缓存,浏览器和服务器之间有一次请求交互。
情形二:若修改时间和文件内容判断有任意一个没有通过,则服务器会受理此次请求,之后的操作同①
① 只有get请求会被缓存,post请求不会
Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修 改。常见的是使用If-None-Match。请求一个文件的流程可能如下:
==第一次请求=
1.客户端发起 HTTP GET 请求一个文件;
2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如"2e681a-6-5d044840")(假设服务器支持Etag生成和已经开启了Etag).状态码200
==第二次请求=
客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag:2e681a-6-5d0448402.服务器判断发送过来的Etag和计算出 来的Etag匹配,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;流程很 简单,问题是,如果服务器又设置了Cache-Control:max-age和Expires呢,怎么办
答案是同时使用,也就是说在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,
服务器才能返回304.(不要陷入到底使用谁的问题怪圈)
Etag 主要为了解决 Last-Modified 无法解决的一些问题。
渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
sql注入原理
就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
总的来说有以下几点:
1)永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引 号和双"-"进行转换等。
2)永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
3)永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4)不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意 html标签或者javascript代码。比如:攻击者在论坛中放一个
看似安全的链接,骗取用户点击后,窃取cookie中的用户私密信息;或者攻击者在论坛中加一个恶意表单,
当用户提交表单的时候,却把信息传送到攻击者的服务器中,而不是用户原本以为的信任站点。
XSS防范方法
首先代码里对用户输入的地方和变量都需要仔细检查长度和对”<”,”>”,”;”,”’”等字符做过滤;其次任何内容 写到页面之前都必须加以encode,避免不小心把html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS 攻击。
首先,避免直接在cookie 中泄露用户隐私,例如email、密码等等。
其次,通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。
如果网站不需要再浏览器端对cookie 进行操作,可以在Set-Cookie 末尾加上HttpOnly 来防止javascript 代码直接获取cookie 。
尽量采用POST 而非GET 提交表单
XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。
要完成一次CSRF攻击,受害者必须依次完成两个步骤: 登录受信任网站A,并在本地生成Cookie。
在不登出A的情况下,访问危险网站B。
CSRF的防御
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。通过验证码的方法
worker主线程:
1)通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。
2)通过worker.postMessage( data) 方法来向worker发送数据。3)绑定worker.onmessage方法来接收worker发送过来的数据。4)可以使用 worker.terminate() 来终止一个worker的执行。
WebSocket是Web应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个Html5协议, WebSocket的连接是持久的,他通过在客户端和服务器之间保持双工连接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定时间间隔去轮询。
CSRF攻击
CSRF即Cross-site request forgery(跨站请求伪造),是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
假如黑客在自己的站点上放置了其他网站的外链,例如"www.weibo.com/api,默认情况下,浏览器会带着weibo.com的cookie访问这个网址,如果用户已登录过该网站且网站没有对CSRF攻击进行防御,那么服务器就会认为是用户本人在调用此接口并执行相关操作,致使账号被劫持。
如何防御CSRF攻击
验证Token:浏览器请求服务器时,服务器返回一个token,每个请求都需要同时带上token和cookie才会被认为是合法请求
验证Referer:通过验证请求头的Referer来验证来源站点,但请求头很容易伪造
设置SameSite:设置cookie的SameSite,可以让cookie不随跨域请求发出,但浏览器兼容不一
xss攻击
XSS即Cross Site Scripting(跨站脚本攻击),指的是通过利用网页开发时留下的漏洞,注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。常见的例如在评论区植入JS代码,用户进入评论页时代码被执行,造成页面被植入广告、账号信息被窃取
XSS攻击有哪些类型
存储型:即攻击被存储在服务端,常见的是在评论区插入攻击脚本,如果脚本被储存到服务端,那么所有看见对应评论的用户都会受到攻击。
反射型:攻击者将脚本混在URL里,服务端接收到URL将恶意代码当做参数取出并拼接在HTML里返回,浏览器解析此HTML后即执行恶意代码
DOM型:将攻击脚本写在URL中,诱导用户点击该URL,如果URL被解析,那么攻击脚本就会被运行。和前两者的差别主要在于DOM型攻击不经过服务端
如何防御XSS攻击
输入检查:对输入内容中的
设置httpOnly:很多XSS攻击目标都是窃取用户cookie伪造身份认证,设置此属性可防止JS获取cookie
开启CSP,即开启白名单,可阻止白名单以外的资源加载和运行
1.用户输入ur|并回车
2.浏览器进程检查url,组装协议,构成完整的url
3.浏览器进程通过进程问通信(IPC) 把url请求发送给网络进程
4.网络进程接收到url请求后检查本地缓存是否缓存了该请求资源,如果有则将该资源返回给浏览器进程
5.如果没有,网络进程向web服务器发起http请求(网络请求),请求流程如下:
1)进行DNS解析,获取服务器ip地址
2)利用ip地址和服务器建立tcp连接
3)构建请求头信息
4)发送请求头信息
5)服务器响应后,网络进程接收响应头和响应信息,并解析响应内容
6.网络进程解析响应流程:
1)检查状态码,如果是301/302,则需要重定向,从Location自动中读取地址,重新进行第4步
7.准备渲染进程
1)浏览器进程检查当前url是否和之前打开的道染进程根域名是否相同,如果相同,则复用原来的进程,如果不同,则开启新的渲染进程
8.传输数据、更新状态
1)渲染进程准备好后,浏览器向渲染进程发起"提交文档”的消息,渲染进程接收到消息和网络进程建立传输数据的“管道"
2)渲染进程接收完数据后,向浏览器发送“确认提交”
3)浏览器进程接收到确认消息后更新浏览器界面状态:安全、地址栏url、 前进后退的历史状态、更新web页面。
1.HTML被HTML解析器解析成DOM Tree, CSS则被CSS解析器解析成CSSOM Tree
2.DOM Tree和CSSOM Tree解析完成后,被附加到一起,形成渲染树(Render Tree)
3.节点信息计算(重排),这个过程被叫做Layout(Webkit)或者Reflow(Mozilla)。即根据渲染树计算每个节点的几何信息生成布局
4.渲染绘制(重绘),这个过程被叫做(Painting 或者 Repaint)。即根据计算好的信息绘制整个页面
5.Display显示到屏幕上
重排:当DOM的变化引发了元素几何属性的变化,比如改变元素的宽高,元素的位置,导致浏览器不得不重新计算元素的几何属性,并重新构建渲染树,这个过程称为“重排”
重绘:当DOM样式的改变并不影响它在文档流中的位置时,例如更改了字体颜色,浏览器会将新样式赋予给元素并重新绘制的过程称,这个过程就是“重绘”
会引起重排的操作:
页面首次渲染。
浏览器窗口大小发生改变——resize事件发生时。
元素尺寸或位置发生改变——定位、边距、填充、边框、宽度和高度。
元素内容变化(文字数量或图片大小等等)。
元素字体大小变化。
添加或者删除可见的DOM元素。
激活CSS伪类(例如::hover)。
设置style属性
查询某些属性或调用某些方法
优化策略:
减少DOM操作
1.最小化DOM访问次数,尽量缓存访问DOM的样式信息,避免过度触发回流。
2.如果在一个局部方法中需要多次访问同一个dom,可以在第一次获取元素时用变量保存下来,减少遍历时间。
3.用事件委托来减少事件处理器的数量。
4.用querySelectorAll()替代getElementByXX()。
减少重排
1.避免设置大量的style内联属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性
2.不要使用table布局,因为table中某个元素一旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
3.尽量少使用display:none可以使用visibility:hidden代替,display:none会造成重排,visibility:hidden只会造成重绘。
4.使用resize事件时,做防抖和节流处理。
css及优化动画
1.少用css表达式
2.减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
3.可以把动画效果应用到position属性为absolute或fixed的元素上,这样对其他元素影响较小
4.动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
5.开启动画的GPU加速,把渲染计算交给GPU。
什么是浏览器缓存
浏览器的缓存机制指的是通过在一段时间内保留已接收到的 web 资源的一个副本,如果在资源的有效时间内,发起了对这个资源的再一次请求,那么浏览器会直接使用缓存的副本,而不是向服务器发起请求。使用 web 缓存可以有效地提高页面的打开速度,减少不必要的网络带宽的消耗。web 资源的缓存策略一般由服务器来指定,可以分为两种,分别是强缓存策略和协商缓存策略。
强缓存
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发起请求。强缓存策略可以通过两种方式来设置,分别是 http 响应头信息中的 Expires 属性和 Cache-Control 属性。其中Cache-Control优先级比Expires高。
服务器通过在响应头中添加 Expires 属性,来指定资源的过期时间。在过期时间以内,该资源可以被缓存使用,不必再向服务器发送请求。这个时间是一个绝对时间,它是服务器的时间,因此可能存在这样的问题,就是客户端的时间和服务器端的时间不一致,或者用户可以对客户端时间进行修改的情况,这样就可能会影响缓存命中的结果。
Expires 是 http1.0 中的方式,因为它的一些缺点,在 http 1.1 中提出了一个新的头部属性就是 Cache-Control 属性,它提供了对资源的缓存的更精确的控制。它有很多不同的值,常用的比如我们可以通过设置 max-age 来指定资源能够被缓存的时间的大小,这是一个相对的时间,它会根据这个时间的大小和资源第一次请求时的时间来计算出资源过期的时间,因此相对于 Expires来说,这种方式更加有效一些。常用的还有比如 private ,用来规定资源只能被客户端缓存,不能够代理服务器所缓存。还有如 no-store ,用来指定资源不能够被缓存,no-cache 代表该资源能够被缓存,但是立即失效,每次都需要向服务器发起请求。
一般来说只需要设置其中一种方式就可以实现强缓存策略,当两种方式一起使用时,Cache-Control 的优先级要高于 Expires 。
协商缓存
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。协商缓存也可以通过两种方式来设置,分别是 http 头信息中的 Etag 和 Last-Modified 属性。
服务器通过在响应头中添加 Last-Modified 属性来指出资源最后一次修改的时间,当浏览器下一次发起请求时,会在请求头中添加一个 If-Modified-Since 的属性,属性值为上一次资源返回时的 Last-Modified 的值。当请求发送到服务器后服务器会通过这个属性来和资源的最后一次的修改时间来进行比较,以此来判断资源是否做了修改。如果资源没有修改,那么返回 304 状态,让客户端使用本地的缓存。如果资源已经被修改了,则返回修改后的资源。使用这种方法有一个缺点,就是 Last-Modified 标注的最后修改时间只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,那么文件已将改变了但是 Last-Modified 却没有改变,这样会造成缓存命中的不准确。
因为 Last-Modified 的这种可能发生的不准确性,http 中提供了另外一种方式,那就是 Etag 属性。服务器在返回资源的时候,在头信息中添加了 Etag 属性,这个属性是资源生成的唯一标识符,当资源发生改变的时候,这个值也会发生改变。在下一次资源请求时,浏览器会在请求头中添加一个 If-None-Match 属性,这个属性的值就是上次返回的资源的 Etag 的值。服务接收到请求后会根据这个值来和资源当前的 Etag 的值来进行比较,以此来判断资源是否发生改变,是否需要返回资源。通过这种方式,比 Last-Modified 的方式更加精确。
当 Last-Modified 和 Etag 属性同时出现的时候,Etag 的优先级更高。使用协商缓存的时候,服务器需要考虑负载平衡的问题,因此多个服务器上资源的 Last-Modified 应该保持一致,因为每个服务器上 Etag 的值都不一样,因此在考虑负载平衡时,最好不要设置 Etag 属性。
总结
在实际的缓存机制中,强缓存策略和协商缓存策略是一起合作使用的。浏览器首先会根据请求的信息判断,若强制缓存(Expires和Cache-Control)生效则直接使用缓存资源,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果和标识,再存入浏览器缓存中;生效则返回304,继续使用缓存
预解析:检查语法错误但不生成AST
生成AST:经过词法/语法分析,生成抽象语法树
生成字节码:基线编译器(Ignition)将AST转换成字节码
生成机器码:优化编译器(Turbofan)将字节码转换成优化过的机器码,此外在逐行执行字节码的过程中,如果一段代码经常被执行,那么V8会将这段代码直接转换成机器码保存起来,下一次执行就不必经过字节码,优化了执行速度
引用计数:给一个变量赋值引用类型,则该对象的引用次数+1,如果这个变量变成了其他值,那么该对象的引用次数-1,垃圾回收器会回收引用次数为0的对象。但是当对象循环引用时,会导致引用次数永远无法归零,造成内存无法释放。
标记清除:垃圾收集器先给内存中所有对象加上标记,然后从根节点开始遍历,去掉被引用的对象和运行环境中对象的标记,剩下的被标记的对象就是无法访问的等待回收的对象。
栈内存调用栈上下文切换后就被回收,比较简单
V8的堆内存分为新生代内存和老生代内存,新生代内存是临时分配的内存,存在时间短,老生代内存存在时间长
新生代内存回收机制
新生代内存容量小,64位系统下仅有32M。新生代内存分为From、To两部分,进行垃圾回收时,先扫描From,将非存活对象回收,将存活对象顺序复制到To中,之后调换From/To,等待下一次回收
老生代内存回收机制
晋升:如果新生代的变量经过多次回收依然存在,那么就会被放入老生代内存中
标记清除:老生代内存会先遍历所有对象并打上标记,然后对正在使用或被强引用的对象取消标记,回收被标记的对象
整理内存碎片:把对象挪到内存的一端
减少 HTTP 请求数
1.合并 JavaScript、CSS 等文件,将浏览器一次访问需要的javascript和CSS合并成一个文件,这样浏览器就只需要一次请求。
2.使用CSS Sprite:将背景图片合并成一个文件,通过background-image 和 background-position 控制显示。逐步被 Icon Font 和 SVG Sprite 取代。
3.内容分片,将请求划分到不同的域名上。
4.LazyLoad Images (这条策略实际上并不一定能减少 HTTP请求数,但是却能在某些条件下或者页面刚加载时减少 HTTP请求数)
5.使用浏览器缓存,将CSS、javascript、logo、图标这些更新频率较低的静态资源文件缓存在浏览器中
减少 DNS 查询
首次访问、没有相应的 DNS 缓存时,域名越多,查询时间越长。所以应尽量减少域名数量。但基于并行下载考虑,把资源分布到 2 个域名上(最多不超过 4 个)。这是减少 DNS 查询同时保证并行下载的折衷方案。
避免重定向
客户端收到服务器的重定向响应后,会根据响应头中 Location 的地址再次发送请求。重定向会影响用户体验,尤其是多次重定向时,用户在一段时间内看不到任何内容,只看到浏览器进度条一直在刷新。
缓存 Ajax 请求
最重要的的优化方式是缓存响应结果
延迟加载 | 延迟渲染
将首屏以外的 HTML 放在不渲染的元素中,如隐藏的 ,或者 type 属性为非执行脚本的
预先加载
预先加载利用浏览器空闲时间请求将来要使用的资源,以便用户访问下一页面时更快地响应。
减少 DOM 元素数量
复杂的页面不仅下载的字节更多,JavaScript DOM 操作也更慢。例如,同是添加一个事件处理器,500 个元素和 5000 个元素的页面速度上会有很大区别。
划分内容到不同域名
浏览器一般会限制每个域的并行线程(一般为 6 个,甚至更少),使用不同的域名可以最大化下载线程,但注意保持在 2-4 个域名内,以避免 DNS 查询损耗。
尽量减少 iframe 使用
使用 iframe 可以在页面中嵌入 HTML 文档,但有利有弊。
避免 404 错误
一些网站设计很酷炫、有提示信息的 404 页面,有助于提高用户体验,但还是浪费服务器资源。尤其糟糕的是外部脚本返回 404,不仅阻塞其他资源下载,浏览器还会尝试把 404 页面内容当作 JavaScript 解析,消耗更多资源。
使用 CDN
相比分布式架构的复杂和巨大投入,静态内容分发网络(CDN)可以以较低的投入,获得加载速度有效提升。
启用 Gzip
Gzip 压缩通常可以减少 70% 的响应大小,对某些文件更可能高达 90%,比 Deflate 更高效。主流 Web 服务器都有相应模块,而且绝大多数浏览器支持 gzip 解码。所以,应该对 HTML、CSS、JS、XML、JSON 等文本类型的内容启用压缩。
避免图片 src 为空
虽然 src 属性为空字符串,但浏览器仍然会向服务器发起一个 HTTP 请求
减少 Cookie 大小
Cookie 被用于身份认证、个性化设置等诸多用途。Cookie 通过 HTTP 头在服务器和浏览器间来回传送,减少 Cookie 大小可以降低其对响应速度的影响。
把样式表放在 head 中
把样式表放在 中可以让页面渐进渲染,尽早呈现视觉反馈,给用户加载速度很快的感觉。这对内容比较多的页面尤为重要,用户可以先查看已经下载渲染的内容,而不是盯着白屏等待。
不要使用 CSS 表达式
CSS 表达式可以在 CSS 里执行 JavaScript,仅 IE5-IE7 支持,IE8 标准模式已经废弃。CSS 表达式超出预期的频繁执行,页面滚动、鼠标移动时都会不断执行,带来很大的性能损耗。
使用 link标签替代 @import
对于 IE 某些版本,@import 的行为和 放在页面底部一样。所以,不要用它
把脚本放在页面底部
浏览器下载脚本时,会阻塞其他资源并行下载,即使是来自不同域名的资源。因此,最好将脚本放在底部,以提高页面加载速度。
使用外部 JavaScript 和 CSS
外部 JavaScript 和 CSS 文件可以被浏览器缓存,在不同页面间重用,也能降低页面大小。当然,实际中也需要考虑代码的重用程度。如果仅仅是某个页面使用到的代码,可以考虑内嵌在页面中,减少 HTTP 请求数。另外,可以在首页加载完成以后,预先加载子页面的资源。
移除重复脚本
重复的脚本不仅产生不必要的 HTTP 请求,而且重复解析执行浪费时间和计算资源。
减少 DOM 操作
JavaScript 操作 DOM 很慢,尤其是 DOM 节点很多时。
定义
浏览器最重要或者说核心的部分是“Rendering Engine”,可大概译为“渲染引擎”,不过我们一般习惯将之称为“浏览器内核”。负责对网页语法的解释(如标准通用标记语言下的一个应用HTML、JavaScript)并渲染网页。 所以,通常所谓的浏览器内核也就是浏览器所采用的渲染引擎,渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法的解释也有不同,因此同一网页在不同的内核的浏览器里的渲染效果也可能不同,这也是网页编写者需要在不同内核的浏览器中测试网页显示效果的原因。
常见的浏览器内核
IE浏览器:Trident内核,也是俗称的IE内核;
Firefox浏览器:Gecko内核,俗称Firefox内核;
Safari浏览器:Webkit内核;
Opera浏览器:最初是自己的Presto内核,后来是Webkit,现在是Blink内核
Chrome浏览器:以前是Webkit内核,现在是Blink内核;
360浏览器、猎豹浏览器:IE+Chrome双内核;
搜狗、遨游、QQ浏览器:Trident(兼容模式)+Webkit(高速模式);
百度浏览器、世界之窗:IE内核;
2345浏览器:以前是IE内核,现在也是IE+Chrome双内核
1.不同浏览器的标签默认的margin和padding不同
解决方案:css 里增加通配符 * { margin: 0; padding: 0; }
2.文字大小不一致字体大小在不同浏览上不一致。例如font-size:14px,在 IE 中的实际行高是16px,下面有3px留白;在 Firefox 中的实际行高是17px,下面有3px留白,上边1px留白;在 opera 中就更不一样了。
html {
font-size: 14px;
line-height: 14px;
}
3.IE6双边距问题;在 IE6中设置了float , 同时又设置margin , 就会出现边距问题
解决方案:设置display:inline;
4.当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度
解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度
5.图片默认有间距
解决方案:使用float 为img 布局(所有图片左浮)
6.IE9以下浏览器不能使用opacity
.box {
/* 一点其他的样式... */
background-color: #000;
opacity: 0.5;
/* 兼容Firefox浏览器 */
-moz-opacity: 0.5;
filter: alpha(opacity=50);
/* IE6 */
filter: progid:DXImageTransform.Microsoft.Alpha(style=0, opacity=50);
7.边距重叠问题;当相邻两个元素都设置了margin 边距时,margin 将取最大值,舍弃最小值;
解决方案:为了不让边重叠,可以给子元素增加一个父级元素,并设置父级元素为overflow:hidden;
8.cursor:hand 显示手型在safari 上不支持
解决方案:统一使用 cursor:pointer
9.两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出;
解决方案:父级元素设置position:relative
10.css3新属性,加浏览器前缀兼容早期浏览器
-moz- :火狐浏览器
-webkit- : Safari, 谷歌浏览器等使用Webkit引擎的浏览器
-o- Opera:浏览器(早期)
-ms- :IE
11.IE8以下不支持CSS3的background-size属性。
解决方案:使用滤镜filter
12.const问题
Firefox下,可以使用const关键字来定义常量;IE下,只能使用var关键字来定义常量。
解决方案:统一使用var关键字来定义常量。
13.Firefox不支持innerText解决方案:使用textContent:
if (navigator.appName.indexOf("Explorer") > -1) {
document.getElementById('element').innerText = "text";
} else {
document.getElementById('element').textContent = "text";
}
14.事件绑定
IE: dom.attachEvent();
标准浏览器: dom.addEventListener(‘click’,function(event){},false);
15.event事件对象问题
解决方案:var e = e||window.event
16.event事件源对象
解决方案:var srcObj = event.srcElement?event.srcElement:event.target
17.IE浏览器div最小宽度和最小高度不生效的问题IE不认得min-这个定义,但实际上它把正常的width和height当作有min的情况来使。这样问题就大了,如果只用宽度和高度,正常的浏览器里这两个值就不会变,如果只用min-width和min-height的话,IE下面根本等于没有设置宽度和高度。比如要设置背景图片,这个最小宽度是比较重要的。
#box {
width: 80px;
height: 35px;
}
html>body #body {
width: auto;
height: auto;
min-width: 80px;
min-height: 35px;
}
a:link {}
a:visited {}
a:hover {}
a:active {}
19. css hack解决浏览器兼容性不同浏览器,识别不同的样式,csshack本身就是处理浏览器兼容的
/* 0是留给ie8的 */
background-color: yellow0;
/* + ie7定了 */
+background-color: pink;
/* _专门留给神奇的ie6 */
_background-color: orange;
20.获取元素的非行间样式值
//获取元素属性值的兼容写去
function getStyle(obj, attr) {
if (obj.currentStyle) {
//兼容IE
obj.currentStyle[attr];
return obj.currentstyle[attr];
} else {
//IE
return window.getComputedStyle(obj, null)[attr];
}
}
21.阻止事件冒泡传播
// js阻止事件传播,这里使用click事件为例
document.onclick = function (e) {
var e = e || Window.event;
if (e.stopPropagation) {
e.stopPropagation(); // W3C标准
} else {
e.cancelBubble = true; // IE... .
}
}
22.阻止事件默认行为
// js阻止默认事件,一般阻止a链接href, form表单submit提交
document.onclick = function (e) {
var e = e || Window.event;
if (e.preventDefault) {
e.preventDefault(); // W3C标准
} else {
e.returnValue = false; // IE... .
}
}
23.ajax兼容问题
var oAjax = null;
if (window.XMLHttpRequest) {
oAjax = new XMLHttpRequest();
} else {
//只支持E6浏览器
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
同源策略
同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
同源限制
无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
无法接触非同源网页的 DOM
无法向非同源地址发送 AJAX 请求
解决方案
1.设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)
2.调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)
// 父窗口打开一个子窗口
var openWindow = window.open(‘http://test2.com’, ‘title’);
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage(‘Nice to meet you!’, ‘http://test2.com’);
// 监听 message 消息
window.addEventListener(‘message’, function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);
3.jsonp
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
// 处理服务器返回回调函数的数据
jQuery ajax
$.ajax({
url: ‘http://www.test.com:8080/login’,
type: ‘get’,
dataType: ‘jsonp’, // 请求方式为jsonp
jsonpCallback: “handleCallback”, // 自定义回调函数名
data: {}
});
vue-resource
this.$http.jsonp(‘http://www.domain2.com:8080/login’, {
params: {},
jsonp: ‘handleCallback’
}).then((res) => {
console.log(res);
})
4.cors
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置,前端设置根据xhr.withCredentials字段判断是否带有cookie
原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open(‘post’, ‘http://www.domain2.com:8080/login’, true);
xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);
xhr.send(‘user=admin’);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
jQuery ajax
$.ajax({
url: ‘http://www.test.com:8080/login’,
type: ‘get’,
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
vue-resource
Vue.http.options.credentials = true
axios
axios.defaults.withCredentials = true
原因是浏览器会自动带上cookie,而token需要设置header才可
xss: 用户通过各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本劫持cookie或者localStorage等信息,发起请求,之类的操作。从而伪造用户身份相关信息。前端层面token会存在哪儿?不外乎cookie localStorage sessionStorage,这些东西都是通过js代码获取到的。解决方案:过滤标签<>,不信任用户输入, 对用户身份等cookie层面的信息进行http-only处理。
csxf:跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。csrf并不能够拿到用户的任何信息,它只是欺骗用户浏览器,让其以用户的名义进行操作。。解决方案也很简单,对于cookie不信任,对每次请求都进行身份验证,比如token的处理。
被xss攻击了,不管是token还是cookie,都能被拿到,所以对于xss攻击来说,cookie和token没有什么区别。但是对于csrf来说就有区别了。
cookie:用户点击了链接,cookie未失效,导致发起请求后后端以为是用户正常操作,于是进行扣款操作。
token:用户点击链接,由于浏览器不会自动带上token,所以即使发了请求,后端的token验证不会通过,所以不会进行扣款操作。
两者的区别:
出现粘包的原因:
粘包问题的解决: