腾讯面试题总结

1.前端基础

1.1 prototype和 proto 的关系是什么

.__proto__ ===.contructor.prototype //若是一个对象是经过Object.create函数构造出来的,那其__proto__就不必定是.constructor.prototype了 //属性返回对建立此对象的数组函数的引用。 

1.2 meta viewport原理

layout viewport //某些网站会由于viewport太窄而显示错乱,浏览器就默认会把viewport设为一个较宽的值,好比980px。宽度能够经过 document.documentElement.clientWidth来获取 visual viewport //表明浏览器可视区域的大小,宽度能够经过 document.documentElement.innerWidth来获取。 ideal viewport //是一个能完美适配移动设备的viewport,不一样的设备有不一样的ideal viewport。 

1.3 域名收敛是什么

# 浏览器的并发限制: 浏览器对于同一域名下容许的并发请求数做了限制,一般同一域名下最大并发请求数为6个; # 域名发散: 域名发散就是为了突破浏览器对于同一域名并发请求数的限制,使用域名发散为同一个服务申请多个域名,从而能够必定程度上提升并发量;固然,因为创建新的请求须要必定的代价,所以须要在域名发散与域名收敛间进行trade off,一般发散的域名个数为2-4个; # 域名收敛: 域名收敛就是将静态资源放在一个域名下不进行发散,这主要是为了适应移动端的发展需求;一般DNS是一个开销较大的操做,而移动端因为网络带宽和实时性、资源等的限制,这些开销对移动端的用户体验是致命的,所以须要进行域名收敛; 

1.4 float和display:inline-block;的区别

共性:
①inline-block: 是把一个元素的display设置为块状内联元素,意思就是说,让一个元素的容器inline展现,而且里面的内容block展现;inline属性使元素内联展现,内联元素设置宽度无效,相邻的inline元素会在一行显示不换行,直到本行排满为止。block的元素始终会独占一行,呈块状显示,可设置宽高。因此inline-block的元素就是宽高可设置,相邻的元素会在一行显示,直到本行排满,也就是让元素的容器属性为block,内容为inline。 ②float: 设置元素的浮动为左或者右浮动,当设置元素浮动时,相邻元素会根据自身大小,排满一行,若是父容器宽度不够则会换行。当咱们设置了元素的浮动时,这个元素就脱离了文档流,相邻元素会呈环绕装排列。 二者共同点是均可以实现元素在一行显示,而且能够自由设置元素大小。 区别: ①inline-block: 水平排列一行,即便元素高度不一,也会以高度最大的元素高度为行高,即便高度小的元素周围留空,也不回有第二行元素上浮补位。能够设置默认的垂直对齐基线。 ②float: 让元素脱离当前文档流,呈环绕装排列,如赶上行有空白,而当前元素大小能够挤进去,这个元素会在上行补位排列。默认是顶部对齐。 

1.5 前端优化策略列举

1、页面级优化
    1. 减小 HTTP请求数 减小 HTTP请求数的主要途径包括: (1). 从设计实现层面简化页面 (2). 合理设置 HTTP缓存 (3). 资源合并与压缩 (4). CSS Sprites (5). Inline Images (6). Lazy Load Images 2. 将外部脚本置底(将脚本内容在页面信息内容加载后再加载) 3. 异步执行 inline脚本(其实原理和上面是同样,保证脚本在页面内容后面加载。) 4. Lazy Load Javascript(只有在须要加载的时候加载,在通常状况下并不加载信息内容。),能够经过构建工具实现,好比配合路由加载 5. 将 CSS放在 HEAD中 6. 减小没必要要的 HTTP跳转 7. 避免重复的资源请求 2、代码级优化 1.Reflow & Repaint reflow:几乎是没法避免的。如今界面上流行的一些效果,好比树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引发浏览器的 reflow。鼠标滑过、点击……只要这些行为引发了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引发它内部、周围甚至整个页面的从新渲 染。一般咱们都没法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。 repaint:若是只是改变某个元素的背景色、文 字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引发浏览器 repaint(重绘)。repaint 的速度明显快于 reflow (1):不要经过父级来改变子元素样式,最好直接改变子元素样式,改变子元素样式尽量不要影响父元素和兄弟元素的大小和尺寸 (2):尽可能经过class来设计元素样式,切忌用style 2.慎用 with with(obj){ p = 1}; 代码块的行为其实是修改了代码块中的 执行环境 ,将obj放在了其做用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,若是没有再依次按做用域链向上查找,所以使用 with至关于增长了做用域链长度。而每次查找做用域链都是要消耗时间的,过长的做用域链会致使查找性能降低。 3.避免使用 eval和 Function 4.减小做用域链查找(这方面设计到一些内容的相关问题) 做用域链查找问题,这一点在循环中是尤为须要注意的问题。若是在循环中须要访问非本做用域下的变量时请在遍历以前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤为重要,由于全局变量处于做用域链的最顶端,访问时的查找次数是最多的。 5.数据访问 Javascript中的数据访问包括直接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问须要更大的开销。 6.字符串拼接 在 Javascript中使用"+" 号来拼接字符串效率是比较低的,由于每次运行都会开辟新的内存并生成新的字符串变量,而后将拼接结果赋值给新变量。与之相比更为高效的作法是使用数组的 join方法,即将须要拼接的字符串放在数组中最后调用其 join方法获得结果。不过因为使用数组也有必定的开销,所以当须要拼接的字符串较多的时候能够考虑用此方法。 7.CSS选择符 8.Image压缩 9.完整的前端优化还应该包括不少其余的途径,例如 CDN、 Gzip、多域名、无 Cookie服务器 

1.6 首屏、白屏时间如何计算

//load: 页面上全部的资源(图片,音频,视频等)被加载之后才会触发load事件
//DOMContentLoaded: 当文档中没有脚本时,浏览器解析完文档便能触发(ie6/7 onreadystatechange;ie<5 document.documentElement.doScroll("left")) 一般认为浏览器开始渲染 <body> 标签或者解析完 <head> 标签的时刻就是页面白屏结束的时间点。可是得考虑到css和js的阻塞。”加载是并行的,执行是串行的“的结果。html开始加载的时候,浏览器会将页面外联的css文件和js文件并行加载,若是一个文件还没回来,它后面的代码是不会执行的。刚刚咱们的demo,咱们阻塞了css文件几秒,此时js文件由于并行已经加载回来,但因为css文件阻塞住,因此后面 JsStartTime 的赋值语句是不执行的!当咱们放开阻塞,此时才会运行到 JsStartTime 的赋值、js文件的解析、JsEndTime的赋值,因为大头时间加载早已完成,因此 JsEndTime 和 JsStartTime 的差值很是小。 

1.7 闭包

//闭包是函数和声明该函数的词法环境的组合,简单的说就是经过函数保留词法环境 function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12 //应用 for(var i=0;i<severalObj.length;i++){ (function(i){ severalObj[i].onclick=function(){......} })(i); } 

1.8 做用域链

做用域链: 当代码在一个环境中执行时,会建立变量对象的一个做用域链。做用域链的用途是保证对执行环境有权访问的全部变量和函数的有序访问。做用域链的前端始终是当前执行的代码所在环境的变量对象。若是这个环境是函数,则将其活动对象做为变量对象。活动对象在最开始时只包含一个变量,即arguments对象。做用域链的下一个变量对象来自包含环境,而在下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境;全局执行环境的变量对象始终都是做用域链中的最后一个对象。 执行环境(Execution Context): 每一个函数都有本身的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行后,栈将其环境弹出,把控制权返回给以前的执行环境。 执行环境的创建分为两个阶段:进入执行上下文(建立阶段)和执行阶段(激活/执行阶段) (1)进入上下文阶段:发生在函数调用时,但在执行具体代码以前。具体完成建立做用域链;建立变量、函数和参数以及求this的值 (2)执行代码阶段:主要完成变量赋值、函数引用和解释/执行其余代码 总的来讲能够将执行上下文看做是一个对象 变量对象(Variable Object):每个执行环境都对应一个变量对象,在该执行环境中定义的全部变量和函数都存放在其对应的变量对象中。 (1)进入执行上下文时,VO的初始化过程以下: 函数的形参:变量对象的一个属性,其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined; 函数声明:变量对象的一个属性,其属性名和属性值都是函数对象建立出来的,若是变量对象已经办好了相同名字的属性,则替换它的值 变量声明:变量对象的一个属性,其属性名即为变量名,其值为undefined;若是变量名和已经声明的函数名或者函数的参数名,则不会影响已经存在的属性 (2)执行代码阶段,变量对象中的一些属性undefined值将会肯定 这里须要说明一下:函数表达式不包含在变量对象之中 活动对象:当函数被调用的时候,一个特殊的对象–活动对象将会被建立。这个对象中包含形参和arguments对象。活动对象以后会做为函数上下文的变量对象来使用。换句话说,活动对象除了变量和函数声明以外,它还存储了形参和arguments对象。 

1.9 ajax如何实现、readyState五中状态的含义

function createXMLHttpRequest() { var xmlHttp; // 适用于大多数浏览器,以及IE7和IE更高版本 try{ xmlHttp = new XMLHttpRequest(); } catch (e) { // 适用于IE6 try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { // 适用于IE5.5,以及IE更早版本 try{ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e){} } } return xmlHttp; }; 一、get请求 xmlHttp.open("GET", "/ajax_get/?a=1", true); //第一个参数为请求方式,第二个参数为请求的服务器地址,第三个参数表示是否异步请求,默认不传值为true xmlHttp.send(null); //get请求没有请求体数据,可是须要发送null,不然会引发火狐浏览器没法正常发送 二、post请求 xmlHttp.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”); //设置请求头,form表单会默认这个键值对不设定,Web服务器会忽略请求体的内容。 xmlHttp.send(“username=yuan&password=123”) //设置请求体数据 三、状态码和响应内容只有在状态4才能获取到 xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { alert(xmlHttp.responseText); } }; //状态值 0:初始化未完成状态,只是建立了XMLHttpRequest对象,还未调用open()方法; 1:请求已开始,open()方法已调用,但还没调用send()方法; 2:请求发送完成状态,send()方法已调用; 3:开始读取服务器响应; 4:读取服务器响应结束。onreadystatechange事件只会在除0之外的状态下触发。 

1.11 jsonp如何实现

function loadScript(url, func) { var head = document.head || document.getElementByTagName('head')[0]; var script = document.createElement('script'); script.src = url; script.onload = script.onreadystatechange = function() { if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') { func(); script.onload = script.onreadystatechange = null; } }; head.insertBefore(script, 0); } window.baidu = { sug: function(data) { console.log(data); } } loadScript('http://suggestion.baidu.com/su?wd=w', function() { console.log('loaded') }); 

1.12怎么处理跨域

一、经过jsonp跨域 二、CORS 主要工做是在服务端加上响应头res.header("Access-Control-Allow-Origin", "xxx"),只要响应头中包含了请求头(Origin),就能够实现跨域,至关于数据请求的决定权在于服务端是否赞成,所以CORS对于代码的修改也只需修改服务端代码便可。 三、document.domain + iframe (只有在主域相同的时候才能使用该方法) 四、location.hash + iframe 原理是利用location.hash来进行传值。 假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息。 1) cs1.html首先建立自动建立一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面 2) cs2.html响应请求后再将经过修改cs1.html的hash值来传递数据 3) 同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值 注:因为两个页面不在同一个域下IE、Chrome不容许修改parent.location.hash的值,因此要借助于a.com域名下的一个代理iframe 五、window.name + iframe 六、postMessage(HTML5中的XMLHttpRequest Level 2中的API) 七、web sockets (web sockets是一种浏览器的API,它的目标是在一个单独的持久链接上提供全双工、双向通讯。(同源策略对web sockets不适用)) 

1.13 restful的method解释

之前基本就用http的post和get。
restful就是让你把delete put patch这些method给用起来,而不是经过post加上参数action=delete来实现删除操做。 

1.14 get和post的区别

GET和POST本质上就是TCP连接,并没有差异。可是因为HTTP的规定和浏览器/服务器的限制,致使他们在应用过程当中体现出一些不一样。 GET和POST还有一个重大区别,简单的说:GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。 

1.15 事件模型解释

javascript中有两种事件模型:DOM0,DOM2
1. DOM0级事件模型 DOM0级事件模型是早期的事件模型,全部的浏览器都是支持的,并且其实现也是比较简单。代码以下: <p id = 'click'>click me</p> <script> document.getElementById('click').onclick = function(event){ alert(event.target); } </script> 这种事件模型就是直接在dom对象上注册事件名称,这段代码就是在p标签上注册了一个onclick事件,在这个事件函数内部输出点击的目标。而解除事件则更加简单,就是将null复制给事件函数,以下: document.getElementById('click'_).onclick = null; 由此咱们能够知道dom0中,一个dom对象只能注册一个同类型的函数,由于注册多个同类型的函数的话,就会发生覆盖,以前注册的函数就会无效。 2. DOM2级事件模型 2.1 事件捕获和事件冒泡(capture,bubble) 首先,IE8及如下是不支持这种事件模型的。假设咱们点击了ID为inner的div,那么此时的事件流程就是,首先执行捕获阶段:document-html-body-div(outer)。而后执行冒泡阶段:div(inner)-div(outer)-body-html-document。 2.2 DOM2级的注册事件和解除事件 在DOM2级中使用attachEvent/addEventListener和removeEventListener来注册和解除事件(IE8及以前版本不支持)。这种函数较之以前的方法好处是一个dom对象能够注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。 addEventListener('事件名称','事件回调','捕获/冒泡')。第三个参数表明捕获仍是冒泡,true表明捕获事件,false表明冒泡事件。 btn1Obj.attachEvent("onclick",method1); detachEvent(event,function); 假如同时有捕获和冒泡,事件捕获比事件冒泡先执行。 

1.16 编写一个元素拖拽的插件

1.17 编写一个contextmenu的插件

1.18 编写web端cookie的设置和获取方法

//设置 document.cookie="userId=828; path=/;domain=cookieDomain;expires="+date.toGMTString(); document.cookie="str="+escape("I love ajax"); //获取 function getCookie(name){ var strCookie=document.cookie; var arrCookie=strCookie.split("; "); for(var i=0;i<arrCookie.length;i++){ var arr=arrCookie[i].split("="); if(arr[0]==name)return arr[1]; } return ""; } //删除,设置过时 function deleteCookie(name){ var date=new Date(); date.setTime(date.getTime()-10000); document.cookie=name+”=v; expires=”+date.toGMTString(); } 

1.19 兼容ie6的水平垂直居中

1.20 兼容ie的事件封装

//事件处理兼容各类浏览器,采用能力检测方法,所谓能力检测,就是有能力就作,没有能力就不作 //定义一个处理事件的对象,兼容各类浏览器,dom2级事件处理和ie事件,若是这两个事件都不兼容,就采用dom0级处理 var eventUtil ={ addEvent:function(element,type,handler){ if (element.addEventListener) { //非IE浏览器采用dom2级事件处理,type为事件类型如:click,handler为事件处理函数,false表明事件采用冒泡处理模型,若是是true表明 采用捕获型处理模型 //除了netbeans采用捕获型处理模型,其余都采用冒泡型处理模型 //若是是非IE浏览器添加事件为:addEventListener element.addEventListener(type,handler,false); }else if (element.attachEvent) { //若是为IE浏览器,添加事件采用 attachEvent element.attachEvent('on'+type,handler); }else{ element['on'+type] = handler; } }, removeEvent:function(element,type,handler){ if (element.removeEventListener) { //非IE浏览器采用dom2级事件处理,type为事件类型如:click,handler为事件处理函数,false表明事件采用冒泡处理模型,若是是true表明 采用捕获型处理模型 //除了netbeans采用捕获型处理模型,其余都采用冒泡型处理模型 //若是是非IE浏览器添加事件为:removeEventListener element.removeEventListener(type,handler,false); }else if (element.detachEvent) { //若是为IE浏览器,添加事件采用 detachEvent element.detachEvent('on'+type,handler); }else{ //dom0级事件处理,若是删除事件采用赋值null element['on'+type] = null; } }, getEvent:function(event){ //获取事件自己 return event?event:window.event; }, getType:function(event){ //获取事件类型 return event.type; }, getElement:function(event){ //获取事件做用元素 return event.target || event.srcElement; }, preventDefault:function(event){ //阻止默认的事件行为 if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false; } }, stopProPagation:function(event){ //中止事件冒泡 if(event.stopProPagation){ event.stopProPagation(); }else{ event.cancelBubble = true; } } } 

1.21 h5和原生android的优缺点

1.22 编写h5须要注意什么

1. 交互上,慎用向右滑动的操做方式。 缘由:苹果手机上,向右滑动容易触发返回“上一级页面”效果。 2. 交互上,慎用横屏展现效果。 缘由:体验上,须要用户设备开启屏幕旋转功能,才能正常观看,用户操做成本高。 

对不一样屏幕的手机,长宽比例不一,难以展现最佳的视觉效果。javascript

3. 视觉上,功能按钮等,远离页面底部(大概128px,这个尺寸不是固定值) 4. 动画上,序列帧压缩小技巧,静态的画面,保存较高质量。中间运动的模糊状态,大胆的压低画面质量吧。 缘由:压缩体积,运动状态就算有锯齿也不明显。 5. 重构上,视频没法自动播放,首次播放须要用户点击触发。 

1.23 xss和crsf的原理以及怎么预防

1.XSS成因归纳 :XSS其实就是Html的注入问题,攻击者的输入没有通过严格的控制进入了数据库,最终显示给来访的用户,致使能够在来访用户的浏览器里以浏览用户的身份执行Html代码,数据流程以下:攻击者的Html输入—>web程序—>进入数据库—>web程序—>用户浏览器。 解决:使用转义 2.CSRF:冒充用户之手(模拟发请求) 解决:令牌来防止 CSRF 有如下几点要注意: a.虽然请求令牌原理和验证码有类似之处,但不该该像验证码同样,全局使用一个 Session Key。由于请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。若是全局使用一个 Session Key,那么危险系数会上升。原则上来讲,每一个页面的请求令牌都应该放在独立的 Session Key 中。咱们在设计服务器端的时候,能够稍加封装,编写一个令牌工具包,将页面的标识做为 Session 中保存令牌的键。 b.在 ajax 技术应用较多的场合,由于颇有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但不管如何,请不要提供直接获取令牌值的 API。这么作无疑是锁上了大门,却又把钥匙放在门口,让咱们的请求令牌退化为同步令牌。 c.第一点说了请求令牌理论上是可破解的,因此很是重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的作法)。但这两种方式用户体验都很差,因此须要产品开发者权衡。 d.不管是普通的请求令牌仍是验证码,服务器端验证过必定记得销毁。忘记销毁用过的令牌是个很低级可是杀伤力很大的错误。咱们学校的选课系统就有这个问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码能够在屡次请求中使用(只要再也不次刷新验证码图片),一直用到。 

1.24 css优先级

1.25 如何实现点击radio的文字描述控制radio的状态(经过label实现)

1.26 delegate如何实现

1.27 使用Promise封装简单Ajax方法

1.GETcss

function getJSON (url) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { resolve(this.responseText, this) } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send() }) } 

2.POSThtml

function postJSON(url, data) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open("POST", url, true) xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { resolve(JSON.parse(this.responseText), this) } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send(JSON.stringify(data)) }) } 

2.框架原理

2.1 angularjs

2.1.1 angular的directive怎么写

2.1.2 angular的脏检查(双向绑定)是如何实现的

2.1.3 依赖注入如何实现

2.1.4 scope如何实现

2.1.5 $parse模块如何实现(主要本身写了一个相似的库)

2.2 react

2.2.1 react在setState后发生了什么(直接说了setState源码)

在代码中调用setState函数以后,React 会将传入的参数对象与组件当前的状态合并,而后触发所谓的调和过程(Reconciliation)。通过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树而且着手从新渲染整个UI界面。在 React 获得元素树以后,React 会自动计算出新的树与老树的节点差别,而后根据差别对界面进行最小化重渲染。在差别计算算法中,React 可以相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是所有从新渲染。 setState历来不负责更新操做。它的工做只是把state,和callback放进序列,而且把要更新的组件放到dirtyComponents序列 

还记得吗?咱们还在ReactDefalutBatchingStragy的事务中,perform执行完了,还要执行close。 真正执行更新方法的是close里面的flushBatchedUpdates。前端

2.2.2 redux解释

2.2.3 对react有什么了解(直接说了react中虚拟dom内部表示,mount过程源码和同步过程源码)

2.2.4 jsBridge

2.2.5 如何说服对方使用jsBridge

2.2.6 diff算法

传统 diff 算法的复杂度为 O(n^3),显然这是没法知足性能要求的。React 经过制定大胆的策略,将 O(n^3) 复杂度的问题转换成 O(n) 复杂度的问题。 diff 策略: tree diff Web UI 中 DOM 节点跨层级的移动操做特别少,能够忽略不计。 component diff 拥有相同类的两个组件将会生成类似的树形结构,拥有不一样类的两个组件将会生成不一样的树形结构。 element diff 对于同一层级的一组子节点,它们能够经过惟一 id 进行区分。 

2.3 requirejs

2.3.1 amd和cmd区别,怎么了解到这些区别的,是不是去看了规范

AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程当中对模块定义的规范化产出。
相同之处
    RequireJS 和 Sea.js 都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单天然。 不一样之处 二者的主要区别以下: 1.定位有差别。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专一于 Web 浏览器端,同时经过 Node 扩展的方式能够很方便跑在 Node 环境中。 2.遵循的规范不一样。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不一样,致使了二者 API 不一样。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。 3.推广理念有差别。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。 4.对开发调试的支持有差别。Sea.js 很是关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。 5.插件机制不一样。RequireJS 采起的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采起的是通用事件机制,插件类型更丰富。 

2.3.2 requirejs那些常常用的方法,而后对其进行解释

2.4 weex

2.4.1 weex实现大体原理(只写过demo,面试管很好没有难为我,只问了这一个问题)

3.http协议

3.1 accept是什么,怎么用

1.Accept属于请求头, Content-Type属于实体头。 2.Accept表明发送端(客户端)但愿接受的数据类型。 好比:Accept:text/xml; 表明客户端但愿接受的数据类型是xml类型 

3.2 http协议状态码,302和303的区别

3.4 前端缓存如何实现、etag如何实现、etag和cache-control的max-age的优先级哪一个比较高以及为何、cache-control和expire优先级哪一个比较高以及为何

1)Expires是http1.0提出的一个表示资源过时时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT,
2)Cache-Control描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,因此相比较Expires,Cache-Control的缓存管理更有效,安全一些。 3)Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since要配合Cache-Control使用。 Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。 If-Modified-Since:当资源过时时(强缓存失效),发现资源具备Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。 4)Etag/If-None-Match:Etag/If-None-Match也要配合Cache-Control使用。 Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的惟一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后获得的。 If-None-Match:当资源过时时(使用Cache-Control标识的max-age),发现资源具备Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。 

4.node

4.1 Buffer模块是干什么的

在 ECMAScript 2015 (ES6) 引入 TypedArray 以前,JavaScript 语言没有读取或操做二进制数据流的机制。 Buffer 类被引入做为 Node.js API 的一部分,使其能够在 TCP 流或文件系统操做等场景中处理二进制数据流。 

4.2 Stream是什么,使用的两种模式

流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface)。 stream 模块提供了基础的 API 。使用这些 API 能够很容易地来构建实现流接口的对象。 在 flowing 模式下, 可读流自动从系统底层读取数据,并经过 EventEmitter 接口的事件尽快将数据提供给应用。 在 paused 模式下,必须显式调用 stream.read() 方法来从流中读取数据片断。 

4.3 http模块如何将异步处理方式实现成同步处理方式,具体解析请参考http模块如何将异步处理转成同步处理

const http = require("http"); const net = require("net"); // 保存请求的队列,每一个元素都是一个socket let watingQueue = []; // 当前处理的请求 let curtSocket = null; let count = 0; // 创建一个http服务器 let httpServer = http.createServer(function (req, res) { // 延迟一秒中回复 setTimeout(function () { res.end(`request: ${++count}`, "utf8"); }, 1000); res.on("finish", function () { curtSocket = null; // 一个请求结束了,处理下一个请求 dealRequest(); }); }); // 创建一个tcp的服务器(http协议是创建在tcp协议上的) net.createServer(function (socket) { // 将请求压入列队 enqueueSocket(socket); // 处理请求(若是如今真在处理的请求,不作任何处理) dealRequest(); }).listen(4000); function enqueueSocket (socket) { watingQueue.push(socket); } function dealRequest () { if (curtSocket != null || watingQueue.length <= 0) { return; } curtSocket = watingQueue.shift(); httpServer.emit("connection", curtSocket); } 

5.其余问题

5.1 utf8和gbk的区别

UTF-8 (8-bit Unicode Transformation Format) 是一种针对Unicode的可变长度字符编码,又称万国码,它包含全世界全部国家须要用到的字符,是国际编码,通用性强,是用以解决国际上字符的一种多字节编码。由Ken Thompson于1992年建立。UTF-8用1到4个字节编码UNICODE字符,它对英文使用8位/8Bit(即1个字节/1Byte),中文使用24位/24Bit(3个字节/3Byte)来编码。用在网页上能够同一页面显示中文简体繁体及其它语言(如日文,韩文)。 GBK (Chinese Internal Code Specification) 是汉字编码标准之一,全称《汉字内码扩展规范》,中华人民共和国全国信息技术标准化技术委员会1995年12月1日制订,国家技术监督局标准化司、电子工业部科技与质量监督司1995年12月15日联合以技监标函1995 229号文件的形式,将它肯定为技术规范指导性文件。 

GBK是国家标准GB2312基础上扩容后兼容GB2312的标准(GB2312共收录了7445个字符,包括6763个汉字和682个其它符号;GBK共收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字)。GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示(注意,GB系列编码是利用了字节中的最高位和ASCII编码区分的,能够和ASCII码混用。因此全角模式下英文是2字节,半角模式英文仍是1字节)。为了区分中文,将其最高位都设定成1。GBK包含所有中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBD大。java

简单概况就是:
UTF-8英文1字节中文3字节,在编码效率和编码安全性之间作了平衡,适合网络传输,是理想的中文编码方式. GBK英文1字节(半角1字节,全角2字节),中文2字节,GBK的范围比GB2312广,GBK兼容GB2312。 

5.2 知道页面上某个点的坐标,如何获取该坐标上的全部元素

5.3 angular、react和jQuery适合哪些应用场景(建议查看各个框架产生背景)

5.4 7点15分小于180度的夹角是多少

5.5 大数相加

5.6 给5升和6升的水杯如何倒出3升的水

5.7 一班喜欢足球的人60%,喜欢排球的70%,喜欢篮球的80%,求喜欢足球和排球的占多少

5.8 前端异常监测如何实现

5.9 直播点赞按钮的冒泡功能如何实现

5.10 js的uglify如何实现

5.11 项目架构、如何带人(本身带过一个小团队)

5.12 前端工程化方面作了哪些东西