回国半个月的准海带,今天体验了一下第一场技术面试。首先是一套题目,30分钟左右的时间根据自己的水平选难题回答,答完之后之后才进行面试。面试官问了很多基础问题,也很多没能回答上。略受打击。。。


后悔试题没拍照,根据回忆整理:

CSS题目

1.上下左右居中

这个题面试前才看过,但问到还是不能说清楚,还是基础有硬伤
思路为绝对定位,在宽高一定的情况下,上下设置为50%。之后设置margin为负值,margin-top和margin-left为自身高度和宽度的一半,将位置拉回中间。

1
2
3
4
5
6
7
8
9
.content{
position: absolute;
width:400px;
height:400px;
top:50%;
left:50%;
margin:-200px 0 0 -200px;
border:1px solid #008800;
}

2.两栏,左边固定100px,右边自适应

其实做布局这个用的最多最常见,我也说的蛮自信的,可惜我把两个思路的属性说混了。
第一个思路是左边用float:left,右边用margin-left为左栏的宽度。

1
2
3
4
5
6
7
8
9
10
11
12
13
*{
margin: 0;
padding: 0;
}
.left{
float:left;
width:100px;
border: solid #999 1px;
}
.right{
margin-left: 100px;
border: solid #777 1px;
}

第二个思路略复杂,右栏width:100%,float:left,但是这样就会超出屏幕的宽度,于是用负值margin拉回来。但这就出现另一个问题,由于右栏缩到左栏里,所以左栏会遮盖右栏的一部分,所以在右栏内部再镶嵌一层,margin-left为左栏的宽度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*{
margin: 0;
padding: 0;
}
.left{
float:left;
width:100px;
border: solid #999 1px;
margin-right: -100%;
}
.right{
float:left;
width:100%;
border: solid #777 1px;
}
.content{
margin-left: 100px;
}

补充:第三种方式是在整理下面题目的时候发现的,用display:table-cell的自适应。
思路还是,因为table-cell的自适应,将右栏设的尽可能的大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
*{
margin: 0;
padding: 0;
}
.left{
float:left;
width:100px;
border: solid #999 1px;
}
.right{
display: table-cell;
width:3000px;
border: solid #777 1px;
}

3.盒模型

盒模型可以帮助块级元素的定位和计算面积,简单来说W3C的盒模型包括content、padding、border。而IE得盒模型则有些不同,表现在设置宽高的时候,W3C模型下只包含content区域,而IE包括所有区域。
这样,在IE下,设置了宽高之后可以很放心的设定padding,但是对于W3C模型下,设置了宽高之后还要计算padding和border的区域。因此有一个方法叫做box-sizing:border-box。border-box将border和padding区域一同算进设定的宽高内。这样的话添加如下代码,就可以设定padding而用不担心超出设置区域。

1
2
3
4
5
div{
box-sizing:border-box;
-moz-box-sizing:border-box; /* Firefox */
-webkit-box-sizing:border-box; /* Safari */
}

4.几种方法生成三个并排的大小相等的元素

这个问题让我有点蒙,首先想到的是三个元素都用百分比控制

1
2
3
4
5
6
7
8
*{
margin: 0;
padding: 0;
}
.left,.right,.middle{
float:left;
width:33.3%
}

其实还有可以用display:inline-block。回家以后尝试了一下,发现问题是如果这几个元素没有在代码里写在一行,那么最后展现出来的是最后一个元素会被挤到下面一行。
大神男友告诉我hack方法为:

1
margin-right: -4px//可以按照实际调整。

关于inline-block缝隙,推荐一篇文章:去除间距

还有一个方法为tabel-cell,这种方法就是将每一个元素设置的尽可能的大,但由于自适应的特性,这三个元素还是会乖乖地等分的排在一行里。

1
2
3
4
5
6
7
8
*{
margin: 0;
padding: 0;
}
.left,.middle, .right{
display:table-cell;
width:3000px;
}

接着昨天的继续补充

5.CSS3的新特性用过哪些

对于我来说最常用当然是border-radius,让圆角成为方便的存在。
然而他问第二个问题:怎样将方的通过圆角变成圆的?
其实只要

border-radius:50%;

就好了。可惜当时我怕这个不能用百分比,于是说如果50的宽高,半径为25就好。其实这个也没错啦,但也看的出我基础不扎实。

除此之外,box-shadow也是咱常用的属性之一。设置水平、垂直的位移,阴影的模糊、尺寸还有颜色,就可以为元素添加阴影。

box-shadow: 2px 2px 3px #777;

然后我也提了一下border-image这个好用又漂亮的属性。通过设置图片路径,图片的切割方式、还有边框的宽度、溢出,以及平铺或拉伸等呈现方式,可以做出一个漂亮精致的边框。

1
border-image: url(border-image.png) 30/10px/10px round;

关于border-image的每一项属性的用法和限制,可以参考我大神男友的文章CSS 3 border-image 属性详解

面试官还问到了动画:transition、transform和animation的区别?
可惜我目前并没有用CSS做过动画【摊手。。
他专门问到了这个问题,说明CSS3的动画是应用较多的,回来立刻学习。

transform是指转换,可以将元素移动、旋转、倾斜、拉伸。

translate(),从当前位置移动到由给定left和top值的位置。这个例子中,div向右下移动,如果想要往左上移动,则要设置为负值。

1
2
3
4
5
6
7
div{
transform: translate(50px,100px);
-ms-transform: translate(50px,100px); /* IE 9 */
-webkit-transform: translate(50px,100px); /* Safari and Chrome */
-o-transform: translate(50px,100px); /* Opera */
-moz-transform: translate(50px,100px); /* Firefox */
}

rotate(),将元素旋转到给定角度,单位为deg(degree角度),在这个例子中为顺时针30度。负值的话为逆时针旋转。

1
2
3
4
5
6
7
div{
transform: rotate(30deg);
-ms-transform: rotate(30deg); /* IE 9 */
-webkit-transform: rotate(30deg); /* Safari and Chrome */
-o-transform: rotate(30deg); /* Opera */
-moz-transform: rotate(30deg); /* Firefox */
}

skew() ,将元素倾斜到给定角度,单位也是deg,分别围绕着X轴和Y轴翻转。这个例子中,在X轴顺时针翻转30度,Y轴顺时针翻转20度,负值为逆时针翻转。

1
2
3
4
5
6
7
div{
transform: skew(30deg,20deg);
-ms-transform: skew(30deg,20deg); /* IE 9 */
-webkit-transform: skew(30deg,20deg); /* Safari and Chrome */
-o-transform: skew(30deg,20deg); /* Opera */
-moz-transform: skew(30deg,20deg); /* Firefox */
}

scale(),将元素拉伸到指定的倍数,同样设定了X与Y两个方向。这个例子中把宽度拉伸2倍,高度拉伸4倍。有意思的是,负值不是缩小,而是翻转,既水平翻转和垂直翻转。

1
2
3
4
5
6
7
div{
transform: scale(2,4);
-ms-transform: scale(2,4); /* IE 9 */
-webkit-transform: scale(2,4); /* Safari 和 Chrome */
-o-transform: scale(2,4); /* Opera */
-moz-transform: scale(2,4); /* Firefox */
}

transform并没有变化的过程,而是直接生成最终效果。transform还有3D方法,就是多了一个Z轴(Opera不支持)

  • transition是指过渡,可以动画般显示出一个从样式到样式之间的过渡。

上面说过transform没有变化的过程,这样一来就可以动画显示出各种酷炫的效果。
transform的属性包括一个你设定过渡的CSS属性,持续时间,时间曲线还有过渡开始的时间。

比较麻烦的写法,每一项属性单独写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
div{
transition-property: width;
transition-duration: 1s;
transition-timing-function: linear;
transition-delay: 2s;
/* Firefox 4 */
-moz-transition-property:width;
-moz-transition-duration:1s;
-moz-transition-timing-function:linear;
-moz-transition-delay:2s;
/* Safari 和 Chrome */
-webkit-transition-property:width;
-webkit-transition-duration:1s;
-webkit-transition-timing-function:linear;
-webkit-transition-delay:2s;
/* Opera */
-o-transition-property:width;
-o-transition-duration:1s;
-o-transition-timing-function:linear;
-o-transition-delay:2s;
}

简单的写法就是将属性都写在transition中。下面例子中包括了之前我们将transform的旋转,效果比较酷炫。(背景用色有点小私心,不过过渡很漂亮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
div{
width:100px;
height:100px;
background:lavender;
transition:width 2s, height 2s, background 2s;
-moz-transition:width 2s, height 2s, -moz-transform 2s; /* Firefox 4 */
-webkit-transition:width 2s, height 2s, -webkit-transform 2s, background 2s; /* Safari and Chrome */
-o-transition:width 2s, height 2s, background 2s, -o-transform 2s; /* Opera */
}

div:hover{
width:200px;
height:200px;
background:LightSeaGreen;
transform:rotate(180deg);
-moz-transform:rotate(180deg); /* Firefox 4 */
-webkit-transform:rotate(180deg); /* Safari and Chrome */
-o-transform:rotate(180deg); /* Opera */
}

  • animation,用@keyframes规则做动画效果。

如果说transition是过渡中的动画效果,那么animation就是专门做动画的。transition是animation的简化,是当属性发生变化的时候,触发过渡动画。就是上面例子中hover的时候,css的属性变化了,那么在transition里面绑定过得属性动画过渡过去。
animation就复杂多了:@keyframes可以有from to,也可以是百分比表示时间帧。

from-to

1
2
3
4
@keyframes myfirst{
from {background: lavender;}
to {background: LightSeaGreen;}
}

百分比

1
2
3
4
5
6
7
@keyframes myfirst{
0% {background: purple;}
25% {background: lavender;}
50% {background: cyan;}
75% {background: LightSeaGreen;}
100% {background:purple;}
}

然后再将这个@keyframes绑定到一个元素上。
animation提供了更多属性,包括@keyframes名字、持续时间、速度曲线、开始时间、播放次数等。

1
2
3
4
5
6
7
8
9
div{
animation: myfirst 5s linear 2s infinite alternate;
/* Firefox: */
-moz-animation: myfirst 5s linear 2s infinite alternate;
/* Safari 和 Chrome: */
-webkit-animation: myfirst 5s linear 2s infinite alternate;
/* Opera: */
-o-animation: myfirst 5s linear 2s infinite alternate;
}

有了这几个属性,css可以在很多时候取代flash和动图了。


JavaScript题目

可能因为笔试中JS题目较多,所以面试的时候没有问太多。

1.优化代码,事件委托

笔试的题目上给了一段代码让我优化。具体代码记不清,大概是获取的元素,然后循环为每一个添加mouseover和mouseout事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var elementList=document.querySelectorAll("a");
var listLen=elementList.length;
function handler (element,color){
return function(){
element.style.color=color;
};
}
//添加事件方法
function addEvent(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}
}
//循环为元素添加事件
for(i=0;i<listLen;i++){
addEvent(elementList[i],"mouseover",handler(elementList[i],"red"));
addEvent(elementList[i],"mouseout",handler(elementList[i],"black"));
}

然后面试官又问我为什么事件委托效率更高

还是基础硬伤,我只是大概知道什么是事件委托,对于原理还不了解。于是回来又查参考书《Javascript高级程序设计》

事件委托利用了事件冒泡,指定一个事件处理程序,就可以管理某一个类型的所有事件。

书上解释,在DOM树中尽量高的层次上添加一个事件处理程序。那么在他的子孙元素中的事件,最终都会冒泡到这个层次中。例如,列表里有两个项目,我们不要分别设置每一个项目点击时的事件,而是在上层中建立事件委托。

1
2
3
4
<ul id="link">
<li id="home">首页</li>
<li id="resume">简历</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var link = document.querySelector("#link");
//添加事件
function addEvent(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}
}
//获取事件对象,因为奇葩的IE,事件对象要用window.event
function getEvent(event){
return event ? event : window.event;
}
//获取事件目标
function getTarget(event){
return event.target || event.srcElement;
}
//为外层ul添加事件委托
addEvent(link,"click",function(event){
event = getEvent(event);
var target = getTarget(event);
//为每一个li添加事件
switch(target.id){
case "home":
target.innerHTML="首页,<a href='http://myj.name/'>Welcome to my home</a>"
break;
case "resume":
location.href = "http://katherina-miao.github.io/resume/";
break;
}
})

2.添加一个类似email中checklist的双向联动

起初,我的内心是崩溃的。。。
这个题刚开始都没搞清楚是做什么的,一直到做完整个卷子我才又回头看了看这个题。时间有限,都没来得及想就往纸上写。
其实这个题是让我做一个类似email里选择发件人的东西,勾选的时候添加到发件人,取消勾选的时候从发件人里面删除。由于是双向联动,因此要在发件人里点击的时候可以删除,并且取消勾选。好像说的有点乱,看下面代码。

其实主要还是事件绑定,然后添加节点,改变属性。

1
2
3
4
5
<div class="container">
<div class="showbox"></div>
<input type="checkbox" name="email" value="i@myj.name">Kathy</input>
<input type="checkbox" name="email" value="i@zjy.name">Visper</input>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
var emails=document.querySelectorAll("[name=email]");
var showBox=document.querySelector(".showbox");
var length=emails.length;
//添加事件
function addEvent(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}
}
//循环,为每个checkbox添加事件
for(var i=0;i<length;i++){
addEvent(emails[i],"click",function(){
//判断是否被选中
if(this.checked){
var Emailvalue = this.value;
var newBtn=document.createElement("input");
newBtn.setAttribute("type","button");

newBtn.value=Emailvalue;
showBox.appendChild(newBtn);
}
//若取消勾选,则删除相应的button
else{
var Emailvalue = this.value;
var emailBtn=document.querySelector("[type=button][value='"+Emailvalue+"']");
showBox.removeChild(emailBtn);
}
//每次重新调用以更新button
startBtn();
})
}
//获取button列表,为button添加事件
function startBtn(){
var emailBtn=document.querySelectorAll("[type=button]");
if(emailBtn.length){
for(var i=0;i<emailBtn.length;i++){
addEvent(emailBtn[i],"click",function(){
var btnvalue=this.value;
var cancelChoose=document.querySelectorAll("[value='"+btnvalue+"']");
//删除button并取消勾选相应checkbox
for(var j=0;j<cancelChoose.length;j++){
if(cancelChoose[j].getAttribute("type")=="button"){
showBox.removeChild(cancelChoose[j]);
}
else if(cancelChoose[j].getAttribute("type")=="checkbox"){
cancelChoose[j].checked=false;
}
}
})
}
}
}

3.Array的方法

面试官问到Array有几种方法,这个我在面试前曾经简单整理过,所以感觉回答也比较满意。

isArray(),判断是否为Array类型。
join(),将Array类型转换为字符串类型,并用join内的符号间隔开。

队列,栈的用法
push(),将数据项放到数组的后面。
pop(),将数组的最后一项删除并返回。
shift(),将数组的第一项删除并返回。
unshift(),将数据项放到数组的前面。

重排序的方法
reverse(),将数组逆序排列。
sort(),将数组由小到大排列。默认是按照字符串比较,也就是说15比5小。要按照数字排列的话,要设定方法:

1
2
3
4
5
6
var numlist = [0, 5, 15, 20, 10];
function compare (value1, value2){
value2-value1;
}
var listsort = numlist.sort(compare);
alert( listsort );//0, 5, 10, 15, 20 按照数值从小到大

操作Array的方法
concat(),在原有meat数组上创建新数组
slice(),截取从指定位置开始到结束为止(不包含结束位置)的数组项赋给新数组,如果没有第二个参数,则截取从指定位置开始到结束的数组项赋给新数组
splice(),从指定位置(第一个参数)删除指定个数(第二个参数)并插入指定项目(’第三个参数”)

位置方法
indexOf(),从前向后查找位置索引。
lastIndexOf(),从后向前查找位置索引。
这两个方法支持第二个参数,既指定位置然后按照方法向前或向后查找位置。

遍历方法
every()中,每一项运行给定函数,每一项都返回true,否则返回true。
filter()中,每一项运行给定函数,返回true的项。
forEach()中,每一项运行给定函数,无返回。
map()中,每一项运行给定函数,返回调用结果组成的数组。
some()中,每一项运行给定函数,任意一项返回true,否则返回true。

归并方法
reduce()和reduceRight()都接受四个参数:前一个值,当前值,索引和数组对象。
reduce()是从左向右归并,当第一个值和第二个值运行过之后,结果将作为下一次运行的前一个值。
reduceRight()则是从右向左,归并方式与reduce()一样。


算法题

算法题就一个,给定字符串“abcba”,处理得到第一个不重复字母。

对算法实在只是了解个皮毛,所以这个问题估计最后还是写错了。回来后自己写了一个,可以得到答案,但也不知道是不是最优。
思路是首先将字符转换成数组,然后从小到大排序,然后循环对每一个数组项比较前后。因为曾经排序,如果是不重复的那么前后应该都与它不同。

1
2
3
4
5
6
7
8
9
var letterString="abcba";
var letterArray=Array.prototype.slice.apply(letterString);
var arrayLen=letterArray.length;
var sortArray=letterArray.sort();
for(var i=0;i<arrayLen;i++){
if(sortArray[i]!=sortArray[i+1]&&sortArray[i]!=sortArray[i-1]){
alert(sortArray[i]);
}
}

HTTP

1.AJAX过程,AJAX中如何区分get和post,get和post的区别

面试官在这个方面一气儿问了三个问题,可能因为我没一个问题都没能答的全面。

AJAX算是听人说的最多的一个技术,无需加载整个页面的情况下进行局部更新。
再用AJAX技术与服务器交换数据时,首先创建一个XMLHttpRequest对象,在特立独行的IE里是ActiveXObject。

接着我们用open()方法和send()方法,使用get和post会有些区别。然后,请求会发送给服务器,服务器会响应触发onreadystatechange事件,当readyState=4(请求完成)且status=200时,说明服务器已经就绪。然后用responseText或responseXML属性去获得字符串或XML格式的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else{
//奇葩的IE5、6
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","response.php",true);
xmlhttp.send();

xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("showBox").innerHTML=xmlhttp.responseText;
}
}

在AJAX中区别get和post,就要详谈open()方法和send()方法。

get请求常用于向服务器查询信息。

在get请求中,open()的第一个参数为“get”,第二个参数为URL,第三个参数为是否为异步。由于get请求的URL中通常带有参数,这些参数必须要使用encodeURIComponent()方法进行编码,否则会有格式错误。这样send()方法内部的参数可以传入null,传入的参数也会转到URL中。

post请求常用于向服务器提交信息。

在post请求中,open()的第一个参数为“post”,URL中不含有参数,第三个参数一样。post请求的send()方法中需要传入提交数据,可以使用XML或者字符串。在提交表单时,首先要设定请求头部的Content-Type为 application/x-www-form-urlencoded。

xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 

然后将传入的表单信息序列化,方便后端的程序获取数据。对于表单数据序列化,FormData对象可以直接放入send()内:

1
2
3
4
<form id=“user-info”>
用户名:<input type="text" name="username"/>
年龄:<input type="text" name="年龄"/>
</form>
1
2
var form = document.getElementById("user-info");
xhr.send(new FormData(form));

前面提过,get方式中url包含参数,而post中url是“干干净净”的。因为用处不同,post在提交内容的时候没有大小限制。而且post在发送时有内容体,那些提交的信息放在内容体内。


2.JSONP 跨域的特性

说实话我只在用JQuery的时候用过JSONP,只知道可以跨域,但不知道为什么可以。所以在被问到的时候,脑子又是一蒙。

由于跨域安全策略,XMLHttpRequest不能跨域请求,这是AJAX的一个主要限制。
JSONP是通过<script>元素。因为我们知道,<script>可以跨域引用js文件。返回的数据格式为JSON,创建一个回调函数来相应返回的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
var script = document.createElement("script");
script.src = "http://tryjson.org?callback=handler";
document.body.appendChild(script);

//回调函数
function handler(response){
var responseContent={
diatotime:response.datetime,
usedEnergy:response.used.Energy,

}
return responseContent;
}

除了JSONP,用img标签也可以跨域通信。

1
2
var img = new Image();
img.src = "http://www.example.com/id=123";

CORS是跨域请求的另一个方法。在IE浏览器中为XDomainRequest对象,而在其他浏览器中则继续用XMLHttpRequest。区别在于,XDomainRequest对象的open()只有两个参数:请求类型和URL,因为都是异步执行。而其他浏览器在使用open()时,URL要使用绝对路径,既可以跨域请求。

3.提高网页性能的方法

因为刚刚问完AJAX,所以首先反应的是使用AJAX部分刷新。然后我想到了CSS精灵,将小图片放在一起减少HTTP请求。然后想到将script和css从外部引入,然后script放在文档底部。

除此之外,总结一下:在内容上压缩,在请求上减少。压缩图片、脚本和CSS,使用CSS精灵,优化图片,尽量使用引用CSS。在请求上避免重定向,尽量使用AJAX尽量使用GET请求。

在优化性能方面,我没什么研究,还是由于对底层原理不熟【汗。。


这次的面试经历整理了一天多,一是因为实在是基础差,每一题都要查资料,编程题要自己试,二是要激励自己。因为自己是很懒的人,不喜欢上网找文章资料。这次面试算是一个鞭策,将自己漏洞补起来。

希望各路大神评论补充!!本菜鸟道谢~~