标准盒子模型:宽度=内容的宽度(content)+ border + padding (box-sizing)
低版本IE盒子模型:宽度=内容宽度(content+border+padding)
2.从用户输入浏览器输入url到页面最后呈现 有哪些过程?
-
用户输入URL地址
-
浏览器解析URL解析出主机名
-
浏览器将主机名转换成服务器ip地址(浏览器先查找本地DNS缓存列表 没有的话 再向浏览器默认的DNS服务器发送查询请求 同时缓存)
-
浏览器将端口号从URL中解析出来
-
浏览器建立一条与目标Web服务器的TCP连接(三次握手)
-
浏览器向服务器发送一条HTTP请求报文
-
-
关闭连接 浏览器解析文档
-
如果文档中有资源 重复6 7 8 动作 直至资源全部加载完毕
HTML渲染过程
-
HTML解析出DOM Tree
-
CSS解析出Style Rules
-
将二者关联生成Render Tree
-
Layout 根据Render Tree计算每个节点的信息
-
Painting 根据计算好的信息绘制整个页面
3.移动 Web 开发和 PC Web 开发有何不同?
-
兼容性,PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性,因为目前不管是android手机还是ios手机,一般浏览器使用的都是webkit内核,所以说做移动端开发,更多考虑的应该是手机分辨率的适配,和不同操作系统的略微差异化。
-
在部分事件的处理上,移动端多出来的事件是触屏事件,而缺少的是hover事件。 另外包括移动端弹出的手机键盘的处理,这样的问题在PC端都是遇不到的。
-
在布局上,移动端开发一般是要做到布局自适应的,rem此时就有很大的用处了。
-
动画处理,PC端由于要考虑IE的兼容性,所以通常使用JS做动画的通用性会更好一些,但是CSS3做了很大的牺牲, 而在手机端,如果要做一些动画、特效等,第一选择肯定是CSS3, 既简单、效率又高。
-
页面性能,PC端网络一般比较稳定,而移动端网络情况就比较复杂,不稳定的网络连接对页面性能带来的挑战是移动端的页面资源不能太大,否则在恶劣网络情况下时,页面将会无法访问 ,严重影响用户体验。
-
移动端上存在的300ms的延迟,在PC端是没有的。
4.什么叫优雅降级和渐进增强?
渐进增强:一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级:一开始就构建站点的完整功能,然后针对低版本浏览器测试和修复。
5.Node.js的适用场景
NodeJS 处理并发的能力强,但处理计算和逻辑的能力反而很弱。
因此,我们把复杂的逻辑运算搬到前端(客户端)完成,而 NodeJS 只需要提供异步 I/O,这样就可以实现对高并发的高性能处理。
RESTful API
这是 NodeJS 最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求 API,组织数据进行返回即可。
它本质上只是从某个数据库中查找一些值并将它们组成一个响应。
由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。
大量 Ajax 请求的应用
实时聊天、客户端逻辑强大的单页 APP,具体的例子比如说:本地化的在线音乐应用,本地化的在线搜索应用,本地化的在线 APP 等。
Apache 适用场景
Apache 由于其多线程高并发共享内存地址空间的特性,那就意味着如果服务器足够强大,处理器足够高核,Apache 的运作将会非常良好,所以适用于(并发)异步处理相对较少,后台计算量大,后台业务逻辑复杂的应用程序。
6.Node.js的优点和缺点
优点:高并发(最重要的优点)、适合 I/O 密集型应用
缺点:
-
不适合CPU密集型应用(CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致 CPU 时间片不能释放,使得后续 I/O 无法发起)
-
只支持单核CPU,不能充分利用CPU
-
可靠性低,一旦代码某个环节崩溃,整个系统都崩溃 原因:单进程、单线程 解决方案: (1)Nnigx 反向代理,负载均衡,开多个进程,绑定多个端口; (2)开多个进程监听同一个端口,使用cluster模块 (3)线上使用 PM2 管理进程,出现问题自动重启项目
-
Debug 不方便,错误没有 stack trace
7.WEB应用从服务器主动推送Data到客户端有哪些方式?
-
html5 websocket
-
WebSocket 通过 Flash
-
XHR长时间连接
-
XHR Multipart Streaming
-
不可见的Iframe
-
<script>标签的长时间连接(可跨域)
8.写一个通用的事件侦听器函数
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);
9.es6的Set数据结构
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) {}
10.用JS实现数组去重方法
//利用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))
11.JS的call和apply的区别
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
12.Web缓存方案
-
数据库数据缓存
为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提高响应效率。
-
服务器缓存
-
代理服务器缓存
代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。可以把它理解为一个共享缓存,为大量用户提供服务,因此在减少相应时间和带宽使用方面很有效,同一个副本会被重用多次。
-
CDN缓存
CDN缓存,也叫网关缓存、反向代理缓存。CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存没法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器。
-
-
浏览器端缓存
浏览器缓存是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用可以避免重复的网络请求和浏览器快速地读取本地数据,整体上加速网页展示给用户。
-
Web 应用层缓存
应用层缓存指的是从代码层面上,通过代码逻辑和缓存策略,实现对数据,页面,图片等资源的缓存,可以根据实际情况选择将数据存在文件系统或者内存中,减少数据库查询或者读写瓶颈,提高响应效率。
13.HTTP状态码,HTTP协议了解哪些
常见的HTTP状态码:
-
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 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
14.解决跨域的方案
-
JSONP跨域
-
跨域资源共享(CORS)
-
nginx代理跨域
-
Nodejs中间件代理跨域
-
WebSocket 协议跨域
-
document.domain + iframe 跨域
-
location.hash + iframe跨域
-
window.name + iframe跨域
-