标准盒子模型:宽度=内容的宽度(content)+ border + padding (box-sizing)html
低版本IE盒子模型:宽度=内容宽度(content+border+padding)前端
用户输入URL地址html5
浏览器解析URL解析出主机名android
浏览器将主机名转换成服务器ip地址(浏览器先查找本地DNS缓存列表 没有的话 再向浏览器默认的DNS服务器发送查询请求 同时缓存)ios
浏览器将端口号从URL中解析出来nginx
浏览器创建一条与目标Web服务器的TCP链接(三次握手)es6
浏览器向服务器发送一条HTTP请求报文web
数据库
关闭链接 浏览器解析文档跨域
若是文档中有资源 重复6 7 8 动做 直至资源所有加载完毕
HTML解析出DOM Tree
CSS解析出Style Rules
将两者关联生成Render Tree
Layout 根据Render Tree计算每一个节点的信息
Painting 根据计算好的信息绘制整个页面
兼容性,PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性,由于目前不论是android手机仍是ios手机,通常浏览器使用的都是webkit内核,因此说作移动端开发,更多考虑的应该是手机分辨率的适配,和不一样操做系统的略微差别化。
在部分事件的处理上,移动端多出来的事件是触屏事件,而缺乏的是hover事件。 另外包括移动端弹出的手机键盘的处理,这样的问题在PC端都是遇不到的。
在布局上,移动端开发通常是要作到布局自适应的,rem此时就有很大的用处了。
动画处理,PC端因为要考虑IE的兼容性,因此一般使用JS作动画的通用性会更好一些,可是CSS3作了很大的牺牲, 而在手机端,若是要作一些动画、特效等,第一选择确定是CSS3, 既简单、效率又高。
页面性能,PC端网络通常比较稳定,而移动端网络状况就比较复杂,不稳定的网络链接对页面性能带来的挑战是移动端的页面资源不能太大,不然在恶劣网络状况下时,页面将会没法访问 ,严重影响用户体验。
移动端上存在的300ms的延迟,在PC端是没有的。
渐进加强:一开始就针对低版本浏览器进行构建页面,完成基本的功能,而后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级:一开始就构建站点的完整功能,而后针对低版本浏览器测试和修复。
NodeJS 处理并发的能力强,但处理计算和逻辑的能力反而很弱。
所以,咱们把复杂的逻辑运算搬到前端(客户端)完成,而 NodeJS 只须要提供异步 I/O,这样就能够实现对高并发的高性能处理。
这是 NodeJS 最理想的应用场景,能够处理数万条链接,自己没有太多的逻辑,只须要请求 API,组织数据进行返回便可。
它本质上只是从某个数据库中查找一些值并将它们组成一个响应。
因为响应是少许文本,入站请求也是少许的文本,所以流量不高,一台机器甚至也能够处理最繁忙的公司的 API 需求。
实时聊天、客户端逻辑强大的单页 APP,具体的例子好比说:本地化的在线音乐应用,本地化的在线搜索应用,本地化的在线 APP 等。
Apache 因为其多线程高并发共享内存地址空间的特性,那就意味着若是服务器足够强大,处理器足够高核,Apache 的运做将会很是良好,因此适用于(并发)异步处理相对较少,后台计算量大,后台业务逻辑复杂的应用程序。
优势:高并发(最重要的优势)、适合 I/O 密集型应用
缺点:
不适合CPU密集型应用(CPU密集型应用给Node带来的挑战主要是:因为JavaScript单线程的缘由,若是有长时间运行的计算(好比大循环),将会致使 CPU 时间片不能释放,使得后续 I/O 没法发起)
只支持单核CPU,不能充分利用CPU
可靠性低,一旦代码某个环节崩溃,整个系统都崩溃 缘由:单进程、单线程 解决方案: (1)Nnigx 反向代理,负载均衡,开多个进程,绑定多个端口; (2)开多个进程监听同一个端口,使用cluster模块 (3)线上使用 PM2 管理进程,出现问题自动重启项目
Debug 不方便,错误没有 stack trace
html5 websocket
WebSocket 经过 Flash
XHR长时间链接
XHR Multipart Streaming
不可见的Iframe
var EventUtil = { //根据状况分别使用dom2 || IE || dom0方式 来添加事件 addHandler: function(element,type,handler) { if(element.addEventListener) { element.addEventListener(type,handler,false); } else if(element.attachEvent) { element.attachEvent("on" + type,handler); } else { element["on" + type] = handler; } }, //根据状况分别获取DOM或者IE中的事件对象,事件目标,阻止事件的默认行为 getEvent: function(event) { return event ? event: window.event; }, getTarget: function(event) { return event.target || event.srcElement; }, preventDefault: function(event) { if(event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } } //根据状况分别使用dom2 || IE || dom0方式 来删除事件 removeHandler: function(element,type,handler){ if(element.removeHandler) { element.removeEventListener(type,handler,false); } else if(element.detachEvent) { element.detachEvent("on" + type,handler); } else { element["on" + type] = null; } } //根据状况分别取消DOM或者IE中事件冒泡 stopPropagation: function(event) { if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } } } var btn = document.getElementById("myBtn"), handler = function () { alert("Clicked"); }; EventUtil.addHandler(btn,"click",handler); EventUtil.removeHandler(btn,"click",handler);
Set数据结构相似数组,但全部成员的值惟一。
let a = new Set(); [1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x)); for(let k of a){ console.log(k) }; // 1 2 3 4 5
基本使用
let a = new Set([1,2,3,3,4]); [...a]; // [1,2,3,4] a.size; // 4 // 数组去重 [...new Set([1,2,3,4,4,4])];// [1,2,3,4]
方法
add(value):添加某个值,返回 Set 结构自己。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除全部成员,没有返回值。
let a = new Set(); a.add(1).add(2); // a => Set(2) {1, 2} a.has(2); // true a.has(3); // false a.delete(2); // true a => Set(1) {1} a.clear(); // a => Set(0) {}
//利用for嵌套for,而后splice去重 function unique(arr){ for(var i=0; i<arr.length; i++){ for(var j=i+1; j<arr.length; j++){ if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个 arr.splice(j,1); j--; } } } return arr; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr))
apply、call 都是能够改变 this 的指向的,
apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
// apply var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.apply(a,[1,2]) // 3
// call var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.call(a,1,2) // 3
为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提升响应效率。
代理服务器缓存
代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,通过处理后(好比权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运做原理跟浏览器的运做原理差很少,只是规模更大。能够把它理解为一个共享缓存,为大量用户提供服务,所以在减小相应时间和带宽使用方面颇有效,同一个副本会被重用屡次。
CDN缓存
CDN缓存,也叫网关缓存、反向代理缓存。CDN缓存通常是由网站管理员本身部署,为了让他们的网站更容易扩展并得到更好的性能。浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存无法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器。
浏览器缓存是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用能够避免重复的网络请求和浏览器快速地读取本地数据,总体上加速网页展现给用户。
应用层缓存指的是从代码层面上,经过代码逻辑和缓存策略,实现对数据,页面,图片等资源的缓存,能够根据实际状况选择将数据存在文件系统或者内存中,减小数据库查询或者读写瓶颈,提升响应效率。
200 OK 客户端请求成功
301 Moved Permanently 请求永久重定向
302 Moved Temporarily 请求临时重定向
304 Not Modified 文件未修改,能够直接使用缓存的文件。
400 Bad Request 因为客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized 请求未经受权。这个状态代码必须和WWW-Authenticate报头域一块儿使用
403 Forbidden 服务器收到请求,可是拒绝提供服务。服务器一般会在响应正文中给出不提供服务的缘由
404 Not Found 请求的资源不存在,例如,输入了错误的URL
500 Internal Server Error 服务器发生不可预期的错误,致使没法完成客户端的请求。
503 Service Unavailable 服务器当前不可以处理客户端的请求,在一段时间以后,服务器可能会恢复正常。
JSONP跨域
跨域资源共享(CORS)
nginx代理跨域
Nodejs中间件代理跨域
WebSocket 协议跨域
document.domain + iframe 跨域
location.hash + iframe跨域
window.name + iframe跨域