Web常见前端面试题及答案

MarBirchell 7年前
   <h2><strong>Web前端常见面试题及答案</strong></h2>    <p><strong>1、盒子模型</strong></p>    <p>盒子模型包括四部分:内容(content)、填充(padding)、边框(border)、边界(margin)</p>    <p>盒子模型可以分为两种:IE盒子模型和W3C标准盒子模型</p>    <p>区别:两者对于width的计算方式不同,前者width=border+padding+内容宽度,后者width=内容宽度。</p>    <p><strong>2、position包含几种属性?absolute和relative的区别?</strong></p>    <p>static:默认状态、没有定位、正常流</p>    <p>inherit:从父元素集成position属性的值</p>    <p>fixed:生成绝对定位的元素(相对于浏览器窗口进行定位)</p>    <p>absolute:生成绝对定位的元素(相位与static定位以外的第一个父元素定位)</p>    <p>relative:生成相对定位的元素(相对于其正常位置定位)</p>    <p>absolute和relative区别:父元素的padding对relative的子元素布局有影响,absolute的子元素不受影响</p>    <p><strong>3、前端性能优化</strong></p>    <p>减少HTTP请求、使用内容发布网络、压缩组件、使用Expire头、JS放底部、CSS放顶部、避免CSS表达式等。</p>    <p><strong>4、JSONP是什么?它是如何实现跨域的?为什么它可以实现跨域?</strong></p>    <p>JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。</p>    <p>由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求(因为同源策略不阻止动态脚本插入,并且将脚本看作是从提供 Web 页面的域上加载的),然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。</p>    <p><strong>5、浏览器兼容问题</strong></p>    <p>css兼容性问题:①不同浏览器的标签默认的外补丁和内补丁不同,解决方案:用通配符*来设置各个标签的内外补丁是0(即设置margin和padding为0);②div的垂直居中问题 vertical-align:middle;文字居中:将行距增加到和整个div一样,高line-height=行高;③margin加倍问题:设置为float的div在ie下的margin会加倍。解决方案:为这个div设置样式:display:inline;</p>    <p>js兼容性问题:①在标准的事件绑定中绑定事件的方法函数为addEventListener,而IE使用的是attachEvent;②事件处理中event属性的获取不同。标准浏览器是作为参数带入,然后通过e.target获取目标元素;而IE是通过window.event方式获得,通过e.srcElement获取目标元素;</p>    <p><strong>6、JS和JAVA的作用域有什么区别</strong></p>    <p>java是块级作用域,js是函数作用域,没有块级作用域。</p>    <pre>  var name="global";    if(true){        var name="local";        console.log(name)    }    console.log(name);</pre>    <p>这段都输出是“local",如果有块级作用域,明显if语句将创建局部变量name,并不会修改全局name,可是没有这样,所以Js没有块级作用域。</p>    <p><strong>7、闭包问题</strong></p>    <p>闭包:函数能被外部调用到,则该作用连上的所有变量都会被保存下来。</p>    <p>作用:①可以读取函数内部的变量;②相当于划出了一块私有作用域,避免数据污染;③让变量始终保存在内存中</p>    <p>使用全局变量被认为是不好的习惯,而且容易造成错误并且维护成本较高,所以js可以采用闭包的方式读取函数的内部变量。但是如果大量使用闭包就会造成过多的变量始终保存在内存中,会造成内存泄漏。</p>    <p>一个简单的闭包例子:</p>    <pre>  function f1(){    var n=999;    function f2(){      alert(n);    }    return f2;  }  var result=f1();  result(); // 999</pre>    <p><strong>8、js中this的工作原理</strong></p>    <p>①全局范围内:指向全局对象;</p>    <pre>  this;</pre>    <p>②函数调用:指向全局对象</p>    <pre>  foo();</pre>    <p>③方法调用:this指向test对象</p>    <pre>  test.foo();</pre>    <p>④调用构造函数:this指向新创建的对象</p>    <pre>  new foo();</pre>    <p>⑤显示的设置this:使用call或者apply方法时,this指向第一个参数</p>    <pre>  function foo(a, b, c) {}  var bar = {};  foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示  foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3</pre>    <p><strong>9、模块化编程</strong></p>    <p>①AMD(异步模块定义) requirejs</p>    <pre>  defined(id,deps,factory)  require([dependency],function(){})</pre>    <p>异步加载,浏览器不会失去响应</p>    <p>它指定的回调函数,只有前面的模块都加载完成后,才会运行,解决了依赖性问题</p>    <p>②CMD(通用模块定义) seajs</p>    <p>模块定义方式和模块加载时机处理不同</p>    <pre>  defined(id,deps,factory)  function(require,exports,module)  module.exports = ______;</pre>    <p>③区别:AMD依赖前置,在定义模块的时候就要声明其依赖的模块;CMD就近依赖,只有在用到哪个模块的时候再去require;</p>    <p><strong>10、JS继承与原型问题</strong></p>    <p>Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。每一个对象都有原型,在浏览器中它体现在一个隐藏的 <strong>proto</strong> 属性上。</p>    <p>当一个对象需要调用某个方法时,它回去最近的原型上查找该方法,如果没有找到,它会再次往下继续查找。这样逐级查找,一直找到了要找的方法。 这些查找的原型构成了该对象的原型链条。原型最后指向的是null。我们说的原型继承,就是将父对像的方法给子类的原型。子类的构造函数中不拥有这些方法和属性。</p>    <p><strong>11、少用float?</strong></p>    <p>①使用float可能会造成兼容性问题,比如在ie6以下,float元素margin加倍问题;②使用float之后会影响左右元素,有可能造成错位问题(float之后都要clear)</p>    <p>解决:可用display、position转化</p>    <p>①无序链接(ul、li),设定li标签属性:display:inline</p>    <p>②div左右结构,比如在右侧要放一个more(更多)来显示更多信息的时候用到了float:right,可以用定位来做。给包裹more的div设定position:relative,然后more这个标签right:0即可。结构更为清晰一点。</p>    <p><strong>12、一个页面从URL到加载显示完成,都发生了什么?</strong></p>    <p>①通过DNS将该地址解析成IP地址;</p>    <p>②发起网络连接,进行http协议会话:客户端发送报头(请求报头),服务端回馈报头(响应报头)</p>    <p>③返回一个页面(根据页面上的外链的URL重新发送请求获取)</p>    <p>④接收文件完毕,对加载到的资源进行语法解析,以及相应的内部数据结构(网页渲染)</p>    <p><strong>13、队列、堆、栈的区别?</strong></p>    <p>队列是先进先出:就像一条路,有一个入口和一个出口,先进去的就可以先出去。而栈就像一个箱子,后放的在上边,所以后进先出。堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。</p>    <p>栈(Stack)是操作系统在建立某个进程时或者线程为这个线程建立的存储区域。在编程中,例如C/C++中,所有的局部变量都是从栈中分配内存空间,实际上也不是什么分配,只是从栈顶向上用就行,在退出函数的时候,只是修改栈指针就可以把栈中的内容销毁,所以速度最快。</p>    <p>堆(Heap)是应用程序在运行的时候请求操作系统分配给自己内存,一般是申请/给予的过程。由于从操作系统管理的内存分配所以在分配和销毁时都要占用时间,所以用堆的效率低的多!但是堆的好处是可以做的很大,C/C++对分配的Heap是不初始化的。</p>    <p>在Java中除了简单类型(int,char等)都是在堆中分配内存,这也是程序慢的一个主要原因。但是跟C/C++不同,Java中分配Heap内存是自动初始化的。在Java中所有的对象(包括int的wrapper Integer)都是在堆中分配的,但是这个对象的引用却是在Stack中分配。也就是说在建立一个对象时从两个地方都分配内存,在Heap中分配的内存实际建立这个对象,而在Stack中分配的内存只是一个指向这个堆对象的指针(引用)而已。</p>    <p><strong>14、如何居中div?如何居中一个浮动元素?</strong></p>    <p>给div设置一个宽度,然后添加margin:0 auto;</p>    <pre>  div{    width:200px;    margin:0 auto;  }</pre>    <p>居中一个浮动元素</p>    <pre>  div{    width:500px;    height:500px;    magin:-150px 0 0 -250px;    position:relative;    left:50%;    top:50%;  }</pre>    <p><strong>15、什么是线程?进程和线程的关系是什么?</strong></p>    <p>线程可定义为进程内的一个执行单位,或者定义为进程内的一个可调度实体。 在具有多线程机制的操作系统中,处理机调度的基本单位不是进程而是线程。一个进程可以有多个线程,而且至少有一个可执行线程。</p>    <p>打个比喻:进程好比工厂(计算机)里的车间,一个工厂里有多个车间(进程)在运转,每个车间里有一个或多个工人(线程)在协同工作,这些工人就可以理解为线程。</p>    <p>线程和进程的关系:</p>    <p>1.线程是进程的一个组成部分.</p>    <p>2.进程的多个线程都在进程地址空间活动.</p>    <p>3.系统资源是分配给进程的,线程需要资源时,系统从进程的资源里分配给线程.</p>    <p>4.处理机调度的基本单位是线程.</p>    <p><strong>16、React为什么这么火?</strong></p>    <p><strong>17、CSS3中的transform属性和transition属性?</strong></p>    <p>transform:</p>    <p>功能:使元素变形的属性,其配合rotate(旋转角度)、scale(缩放倍数)、skew(扭曲元素)等参数一起使用</p>    <p>语法:</p>    <p>transform:rotate(旋转角度);//正数为顺时针、负数为逆时针;</p>    <p>transform:rotate(30deg);//顺时针旋转30度</p>    <p>transform:rotate(-20deg);//逆时针旋转20度</p>    <p>transform:scale(缩放倍数);</p>    <p>transform:scale(1.20);//放大1.2倍</p>    <p>transition:</p>    <p>功能:设置元素由样式一变为样式二所需要的一些变化效果</p>    <p>语法:transition: <em>property</em> <em>duration</em> <em>timing-function</em> <em>delay</em> ;</p>    <table>     <thead>      <tr>       <th>值</th>       <th>描述</th>      </tr>     </thead>     <tbody>      <tr>       <td>transition-property</td>       <td>规定设置过渡效果的 CSS 属性的名称。</td>      </tr>      <tr>       <td>transition-duration</td>       <td>规定完成过渡效果需要多少秒或毫秒。</td>      </tr>      <tr>       <td>transition-timing-function</td>       <td>规定速度效果的速度曲线。</td>      </tr>      <tr>       <td>transition-delay</td>       <td>定义过渡效果何时开始。</td>      </tr>     </tbody>    </table>    <p>注:使用这两个属性时应考虑到浏览器的兼容性,所以要针对不同的浏览器都添加一次样式,如下:</p>    <pre>  -webkit-transform:rotate(0deg) scale(1.20);   -moz-transform:rotate(0deg) scale(1.20);   transform:rotate(0deg) scale(1.20);</pre>    <p><strong>18、什么是MVVM框架?</strong></p>    <p>MVVM是Model-View-ViewModel的简写。</p>    <p>MVVM 是 Web 前端一种非常流行的开发模式,利用 MVVM 可以使我们的代码更专注于处理业务逻辑而不是去关心 DOM 操作。目前著名的 MVVM 框架有 vue, avalon, angular 等,这些框架各有千秋,但是实现的思想大致上是相同的:数据绑定 + 视图刷新。跟MVC一样,主要目的是分离视图(View)和模型(Model)。View可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。</p>    <p>在MVVM中,数据是核心,由于VIewModel与View之间的双向绑定,操作了ViewModel中的数据(当然只能是监控属性),就会同步到DOM,我们透过DOM事件监控用户对DOM的改动,也会同步到ViewModel。</p>    <pre>  <div id="mobile-list">     <h1 v-text="title"></h1>     <ul>       <li v-for="item in brands">         <b v-text="item.name"></b>         <span v-show="showRank">Rank: {{item.rank}}</span>       </li>     </ul>  </div></pre>    <pre>  var element = document.querySelector('#mobile-list');  var vm = new MVVM(element, {     'title' : 'Mobile List',     'showRank': true,     'brands' : [       {'name': 'Apple', 'rank': 1},       {'name': 'Galaxy', 'rank': 2},      {'name': 'OPPO', 'rank': 3}     ]  });  vm.set('title', 'Top 3 Mobile Rank List'); // => <h1>Top 3 Mobile Rank List</h1></pre>    <p>以上这段如此简洁的代码,就是MVVM框架的一个简单的实现效果。在HTML代码里面,可能会嵌入很多自定义的属性(标记),以此来实现数据的绑定,而且还可以进行一些简单的逻辑处理,比如if和循环等。</p>    <p>react应该也算是MVVM框架,但是与传统的MVVN框架不同的是,react默认数据绑定方式是单向绑定,而vue及angular都是双向绑定;react使用虚拟DOM配合JSX,而vue及angular直接将数据通过属性绑定在真实DOM上的。</p>    <p>MVVM框架的优点:</p>    <p>1、方便测试</p>    <p>在MVC下,Controller基本是无法测试的,里面混杂了个各种逻辑,而且分散在不同的地方。有了MVVM我们就可以测试里面的viewModel,来验证我们的处理结果对不对。</p>    <p>2、便于代码的移植</p>    <p>可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。比如iOS里面有iPhone版本和iPad版本,除了交互展示不一样外,业务逻辑的model是一致的。这样,我们就可以以很小的代价去开发另一个app。</p>    <p>3、独立开发</p>    <p>开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。</p>    <p><strong>19、利用@media screen实现网页布局的自适应。</strong></p>    <p>判断媒体类型,执行不同的css样式属性</p>    <p>重要属性:min-width:设置最小分辨率大小;max-width:设置最大分辨率大小。</p>    <p>①方式一:通过css</p>    <pre>  ///1280分辨率以上(大于1200px)  @media screen and (min-width:1200px){     #content{ width: 1100px; }    #mian,.div1{width: 730px;}    #secondary{width:310px;}  }</pre>    <pre>  //1100分辨率(大于960px,小于1199px)  @media screen and (min-width: 960px) and (max-width: 1199px) {     #content{ width: 960px; }    #main,.div1{width: 650px;}    #secondary{width:250px}  }</pre>    <p>②方式二:通过link引入不同的css文件</p>    <pre>  //意思是当屏幕的宽度大于600小于800时,应用styleB.css  <link rel="stylesheet" type="text/css" href="styleB.css" media="screen and (min-width: 600px) and (max-width: 800px)"></pre>    <p>优点:无需插件和手机主题,对移动设备友好,能够适应各种窗口大小。只需在CSS中添加@media screen属性,根据浏览器宽度判断并输出不同的长宽值。</p>    <p><strong>20、使用原生js实现ajax</strong></p>    <p>创建一个 XMLHttpRequest 对象。如果不支持创建该对象的浏览器,则需要创建 ActiveXObject,具体方法如下:</p>    <pre>  var xmlHttpRequest;  function createXmlHttpRequest(){    if(window.XMLHttpRequest)//非IE      xmlHttpRequest = new XMLHttpRequest();    else if(window.ActiveObject)//IE6+      xmlHttpRequest = new ActiveObject("Msxml2.XMLHTTP");    else//IE6-      xmlHttpRequest = new ActiveObject("Microsoft.XMLHTTP");  }</pre>    <p>提交请求的方法:</p>    <pre>  open(method,url);//分别为提交的方法(GET或者POST)和提交的url  send(content);  onreadystatechange(){    if(xmlHttpRequest.readyState == 4){      if(xmlHttpRequest.state == 200){        //请求成功      }      }else{      //请求失败    }  }</pre>    <p><strong>21、前端安全方面有没有了解?XSS和CSRF如何攻防?</strong></p>    <p>XSS(Cross Site Scripting)是跨站脚本攻击,为了区分CSS,所以缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。</p>    <p>在网页的一些公共区域(例如,建议提交表单或消息公共板的输入表单)输入一些文本,这些文本被其它用户看到,但这些文本不仅仅是他们要输入的文本,同时还包括一些可以在客户端执行的脚本。如:</p>    <pre>  "/> <script>alert(document.cookie);</script><!--</pre>    <p>在文本框中输入以上代码,然后点击提交,就会把用户的cookie弹出来。</p>    <p>XSS漏洞修复</p>    <p>1.将重要的cookies标记为HTTP ONLY。</p>    <p>2.只允许用户输入我们期望的数据。如年龄框只能输入数字。</p>    <p>3.对数据进行HTTP Encode处理。</p>    <p>4.过滤或者移除特殊的HTML标签。</p>    <p>5.过滤JS事件的标签。</p>    <p>CSRF(Cross-site request forgery)是跨站请求伪造。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。其实就是攻击者盗用了你的身份,以你的名义发送恶意请求。</p>    <p>CSRF攻击的思想</p>    <p>用户浏览并登陆信任网站A;通过验证,在用户处产生X的cookie;用户在没有登出X的时候,浏览危险网站B;B要求访问第三方网站A,发出一个请求;根据这个请求,浏览器使用刚才产生的cookie直接访问A。</p>    <p>一个简单的实例</p>    <p>银行网站A,它以GET请求来完成银行转账的操作,如: <a href="http://www.mybank.com/Transfer.php?toBankId=11&money=1000" rel="nofollow,noindex">http://www.mybank.com/Transfer.php?toBankId=11&money=1000</a></p>    <p>危险网站B,它里面有一段HTML的代码如下:</p>    <pre>  <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000></pre>    <p>首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......</p>    <p>CSRF的防御</p>    <p>1.在表单里增加Hash值,以认证这确实是用户发送的请求,然后在服务器端进行Hash值验证。</p>    <p>2.验证码:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串。</p>    <p>20、是否了解什么前沿的技术、或者你自己有什么技术特长、在哪方便有优势?</p>    <p>持续更新中。。。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/0e9a0d460f64</p>    <p> </p>