前端面试题及答案整理(二)
part1 css相关
1 内联元素(inline-element)和块元素(block element)分别有哪些
常见内联元素(行内元素)有a、b、span、i 、em、input、select 、img等
常见的块元素有div、ul、li、h1~h6、talbe、ol、 ul、td、p等
2 浮动相关
浮动布局指将元素脱离普通流/文档流,使其可以左右移动,直至它的外边缘遇到包含框或者另一个浮动框的边缘。浮动框不属于文档中的普通流,当一个元素浮动之后,不会影响到块级元素的布局而只会影响内联元素的排列。
正因为浮动元素脱离了文档流,其父级元素并不知道它的存在,因此会表现为高度为0,无论浮动元素如何变化,其父级元素也不会随它变化将其包裹,这种现象也叫作“高度塌陷”。
下面的例子中,不管#floatdom高度如何变化,#parent高度始终为0,这将导致父元素边框不能被撑开,背景不能显示等问题
<div id="parent"> <div id="floatdom" style="float:left;width:300px;height:300px;"> <div style="clear:both"> </div>
因为高度塌陷的存在(这往往不是我们所期望的),必须要清除浮动,下面介绍清除浮动的几种方式:
•在浮动元素后添加样式含有“clear:both”的元素
<div id="parent"> <div id="floatdom" style="float:left;width:300px;height:300px;"> <div style="clear:both"> </div>
也可以添加br标签,其自带clear:both属性
<div id="parent"> <div id="floatdom" style="float:left;width:300px;height:300px;"> <br/> </div>
利用这种方式清除浮动的优点在于通俗易懂,容易掌握,缺点也很明显,增加了很多无意义的标签,这个在后期维护中是很痛苦的。
•为父元素添加样式“overflow:hidden"
<div id="parent" style="overflow:hidden"> <div id="floatdom" style="float:left;width:300px;height:300px;"> </div>
利用这种方式不存在结构和语义化问题而且代码量极少,然而在内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素。
•利用:after伪元素
<style type="text/css"> .clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; } .clearfix { *zoom:1; } </style> <div id="parent" class="clearfix"> <div id="floatdom" style="float:left;width:300px;height:300px;"> </div>
利用这种方式,仅需在目标元素上添加一个类,也是目前使用最多的一种方式。
reference
3 相对布局(relative)和绝对布局的区别(absolute)
相对布局和绝对布局最本质的区别在于是否脱离文档流。
相对布局未脱离文档流,即设置元素相对布局后,文档流仍然保持其原始的位置,通过设置top、left等属性可设置其相对于原始位置的偏移量。
绝对布局是脱离文档流的,即文档流中的要素并不知道该绝对布局要素的存在,绝对布局的定位是相对于父元素中具有相对布局或绝对布局的要素,若都不存在则相对于body布局。
4 盒模型(box model)
盒模型定义了一个元素的显示形式,包括content(内容)、padding(内边距)、border(边界)以及margin(外边距)几部分组成,目前有两种盒模型标准,一种是w3c标准盒子模型,还有一种是ie盒子模型,采用的是microsoft自己的标准。
这两种盒模型的区别主要在于元素宽度的计算。标准模式下css中定义的width即为content(内容)的宽度,整个元素在页面中占有的宽度,计算公式为:
dom_width = width + padding + border + margin
而在ie盒子模型中,css中定义的width为content + padding + border,因此在ie盒子模型中,整个元素在页面中占有的宽度为(高度同理)
dom_width = width + margin
在css3中利用box-sizing
保留了两种盒子模型,当我们设置box-sizing: content-box
(默认),采用的是w3c标准盒模型,当设置box-sizing:border-box
时,采用的是ie盒模型。
5 css reset(重置)
每个浏览器都有一些自带的样式,而且各个浏览器这些自带的样式往往又存在不同,这给我们布局上带来了一些不便。因此在实践中往往需要对浏览器的css样式进行“清零”,即css reset。最简单的一种reset代码如下:
*{ margin:0; padding:0; }
这种方式虽然简单但太过“暴力”,因为很多要素像div、li等本身默认就没有margin、padding样式,这无异于造成大量冗余,更推荐的方式根据自己需要编写reset代码。
reference:
6 css hack
由于不同的浏览器对css的解析和支持是不同的,这会导致相同的css代码在不同浏览器中的显示方式并不是完全一致的,这就需要通过css hack来解决不同浏览器的兼容性问题。针对不同浏览器写不同的样式的这个过程就称为css hack。
css hack常见的形式有如下几种:
•属性hack
比如ie6能识别_width
以及*width
,而在ie7中能识别*width
,但是不能识别_width
,在firefox中两个都不识别。
•选择符hack
比如ie6能识别*html .class{}
,ie7能识别*+html .class{}
或者*:first-child+html .class{}
。
•条件hack
ie条件注释是微软从ie5开始就提供的一种非标准逻辑语句。比如针对所有ie:
<!–[if ie]> <!–your code–> <![endif]–>
针对ie6及以下版本:
<!–[if lt ie 7]> <!–your code–> <![endif]–>
这类hack不仅对css生效,对写在判断语句里面的所有代码都会生效。
reference
7 优雅降级(graceful degradation)与渐进增强(progressive enhancement)
渐进增强指针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级指一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
两者的区别在于优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。
8 说出遇到的浏览器兼容问题
•不同浏览器中显示的内边距、外边距不同,如ul标签在firefox中默认是有padding值的,而在ie中只有margin有值
利用css reset(参见第5条)
•ie6的双倍边距bug,在块级元素浮动后本来外边距10px,但ie解释为20px
将其该块级元素display设置为inline
•ie6中不支持min-height
min-height的作用是作用是当容器的内容较少时,能保持一个最小的高度,以免破坏了布局或ui设计效果。而当容器内的内容增加的时候,容器能够自动的伸展以适应内容的变化。
通过这种下面的方式可以解决:
#targetdom{ background:#ccc; min-height:100px; height:auto!important; height:100px; overflow:visible; }
•在标准的事件绑定中绑定事件的方法函数为addeventlistener,而ie使用的是attachevent
通过条件判断分别写两条绑定语句或者使用jquery这类web框架库绑定。
•标准浏览器采用事件捕获的方式,而ie采用的是事件冒泡机制
后来标准认为冒泡更合理,利用设置addeventlistener第三个参数兼容两种机制,事件冒泡为默认值。
•事件处理中的event属性ie中获取方式和标准浏览器不同
标准浏览器是作为参数带入,而ie是window.event方式获得,获得目标元素ie为e.srcelement 标准浏览器为e.target
part2 其它
1 了解常用http状态码
200 ok 一切正常,对get和post请求的应答文档跟在后面。
201 created服务器已经创建了文档,location头给出了它的url。
202 accepted 已经接受请求,但处理尚未完成。
304 not modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供if-modified-since头表示客户只想比指定日期更新的文档)。服务器告 诉客户,原来缓冲的文档还可以继续使用。
400 bad request 请求出现语法错误。
404 not found 无法找到指定位置的资源。这也是一个常用的应答。
405 method not allowed 请求方法(get、post、head、delete、put、trace等)对指定的资源不适用。(http 1.1新)
500 internal server error 服务器遇到了意料不到的情况,不能完成客户的请求。
502 bad gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。
2 手写ajax请求
//在ie5和ie6中模拟xmlhttprequest方法 if(window.xmlhttprequest === undefined){ window.xmlhttprequest = function(){ try{ return new activexobject("msxml2.xmlhttp.6.0"); //可用,使用最新activex对象 } catch(e1){ try{ return new activexobject("msxml2.xmlhttp.3.0");//不可用,退后更早的版本 } catch(e2){ throw new error("xmlhttprequest is not supported"); } } } } //get请求 function xhrget(url,callback){ var request = new xmlhttprequest(); request.open('get',url,true); request.onreadystatechange = function(){ if(request.readystate === 4 && request.status == 200){ callback&&callback(request.responsetext); } }; request.send(null); } //post请求 function xhrpost(url,data,callback){ var request = new xmlhttprequest(); request.open('post',url,true); request.setrequestheader('content-type','application/json'); request.onreadystatechange = function(){ if(request.readystate === 4 && request.status == 200){ callback&&callback(request); } }; request.send(json.stringfy(data)); }
这是xmlhttprequest传统的用法,xmlhttprequest level 2提出了很多新的方法,我们常提到的cors也是源自该方法。
要了解详细xhr2推荐 xmlhttprequest level 2 使用指南
3 跨域问题
当我们在页面中通过ajax请求其它服务器的数据时,由于浏览器对于javascript的同源策略,客户端就会发生跨域问题。所谓同源策略,指的是一段脚本只能请求来自相同来源(相同域名、端口号、协议)的资源。
如果上面xmlhttprequest请求的服务地址与当前文件不同源的话,浏览器中会出现如下错误:
那么该如何解决这类跨域问题?
(1)利用cors跨域
"跨域资源共享"(cross-origin resource sharing,简称cors)。cors是是在xhr2中拓展的能力,使用方法很简单,在服务端设置:
header set access-control-allow-origin *
这种设置将接受所有域名的跨域请求,也可以指定具体网址,也可以对域名进行限定:
header set access-control-allow-origin
然而,这种方式的局限性在于要求客户端支持,并且服务端进行相关设置。在这两者满足的情况下,通过cors进行跨域不仅支持所有类型的http请求,而且开发者可以使用普通的xmlhttprequest发起请求和获得数据,比起jsonp有更好的错误处理。
(2)利用jsonp实现跨越
对于较老的浏览器,它们往往不支持cors,因此使用jsonp进行跨域也是很常见的一种方式。
我们知道在网页中通过<script>元素的src指定加载目标脚本时是不受同源策略的影响的,因此可以使用它们从其他服务器请求数据,这种利用<script>元素作为ajax传输的技术就称为jsonp。
jsonp实现的原理如下:
function getjsonp(url, callback){ var funcname = getuniquename();//利用时间戳或指自增计数器获得唯一函数名 url += "?callback=" + funcname; //将函数名作为参数添加至url中 var script = document.createelement('script');//动态构建script标签 //回调函数 getjsonp[funcname] = function(response){ try{ callback(response); //处理响应数据 } finally{ //即使回调函数或响应抛出错误,清除动态增加内容 delete getjsonp[funcname]; script.parentnode.removechild(scirpt); } } //触发http请求 script.src = url; document.body.appendchild(script); }
jsonp也存在一些弊端,首先jsonp支持get不支持post方法,另外使用<script>元素进行ajax请求,这意味着允许web页面可以执行远程服务器发送过来的任何javascript代码,因此对于不信任的服务器,不应该采用该技术。
(3)利用window.name进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置,因此可以借助window.name在不同源的页面中传递数据。
如www.a.com/a.html想要获得www.b.com/b.html中的数据,原理如下:
a) 在b.html中将数据存储在window.name中
b) 在a.html中构建一个隐藏(display:none)的iframe标签,假设id设为proxy,src设置为和a.html同源即可。
c) 通过如下代码在a.html中获取到data
var proxy = document.getelementbyid('proxy'); proxy.onload = function(){ var data = proxy.contentwindow.name;//获取到数据 }
d) 移除相关元素
(4) 使用window.postmessage进行跨域
这种方式比较简单,在a页面中利用windowobj.postmessage(message, targetorigin)向目标页面发送信息,而在b页面中通过监听message事件获取信息。这种方式是在html5中新增的方法,对于ie6、ie7等老版本浏览器无法使用。
4 如何提高网站性能
请参看博主的另外两篇文章:
关于提高网站性能的几点建议
关于提高网站性能的几点建议2
发现新内容会持续更新...
博文作者:vicfeel