前端面试题(面试的回答和学习面试题)
对于技术来说,面试题这的是一个有意思的东西,被技术大牛面试过后真的让你受益匪浅。在渣渣大牛面试过后那叫一个搞笑和装逼(边面试边给你讲,主要讲的都不对,整的有点耐人寻味skr)。但是,虽然那些渣渣大牛们面试问的问题觉得很脑残,但是面试题真的算是一个武功秘籍,不能因为渣渣大牛们的面试而怀疑面试题,因为渣渣们面试问的那不叫面试题。
ok 开始我们的面试题吧(以下都是个人的整理,回答面试题和学习面试题,会持续的更新滴,建议先看右下角的目录,比较多)
一、关于HTML的面试题
1、html5哪些操作可以SEO优化
- title标签;meta标签;header标签;footer标签
元标签(meta标签); - 导航标签(nav标签);文章标签(article标签);左或右侧标签(aside标签)
2、页面导入样式时,使用link和@import有什么区别?
- 1.link属于HTML标签,除了加载CSS外,还能用于定义RSS,定义rel连接属性等作用;而@import是CSS提供,只能加载CSS;
- 2.页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
import是CSS2.1提出的,只在IE5以上才能被识别,而link是HTML标签,无兼容问题;
3、行内元素和块状元素的区别?行内快元素的兼容性使用?(IE8以下)
- 行内元素:会在水平方向排列,不能包含快级元素,设置width无效,height无效(可以设置line-height),margin上下无效,padding上下无效
- 块级元素:各占据一行,垂直方向排列。从新行开始结束接着一个断行
兼容性:display:inline-block;display:inline;zoom:1;
ok 关于html的面试题个人觉得有用的并不多,然后什么doctype的意义,HTML5带来了哪些变化?,html,xhtml,html5之间有什么关系?我觉得正常的面试官不会问你这些的,这也不是重头,先热热身,那我们继续!
二、关于CSS的面试题(持续更新中。。。)
1、如何清除浮动,以及清除浮动的方法
-
1)添加额外标签
,其他标签br等亦可。
在浮动元素末尾添加一个空的标签例如<div class="warp" id="float"> <h2>1)添加额外标签</h2> <div class="main left">.main{float:left;}</div> <div class="side left">.side{float:right;}</div> <div style="clear:both;"></div> </div>
优点:通俗易懂,容易掌握
缺点:可以想象通过此方法,会添加多少无意义的空标签,有违结构与表现的分离。
-
2)父元素设置 overflow:hidden
通过设置父元素overflow值设置为hidden;在IE6中还需要触发 hasLayout ,例如 zoom:1;<div class="warp" id="float" style="overflow:hidden; *zoom:1;"> <h2>2)父元素设置 overflow </h2> <div class="main left">.main{float:left;}</div> <div class="side left">.side{float:right;}</div> </div>
优点:不存在结构和语义化问题,代码量极少
缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素;
-
3)父元素设置 overflow:auto 属性
同样IE6需要触发hasLayout,演示和2差不多优点:不存在结构和语义化问题,代码量极少
缺点:多个嵌套后,firefox某些情况会造成内容全选;IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等,firefox早期版本会无故产生focus等。
-
4)使用:after 伪元素
需要注意的是 :after是伪元素,不是伪类(某些CSS手册里面称之为“伪对象”),很多闭合浮动大全之类的文章都称之为伪类,不过csser要严谨一点,这是一种态度。由于IE6-7不支持:after,使用 zoom:1触发 hasLayout。
.clearfix:before{ content:'';display:table; } .clearfix:after {content:""; display:block; height:0; visibility:hidden; clear:both; } /* 简洁写法 */ .clearfloat:after{display:block;clear:both;content:'';}
优点:结构和语义化完全正确,代码量居中
缺点:复用方式不当会造成代码量增加 -
小结
通过对比,我们不难发现,其实以上列举的方法,无非有两类:
其一,通过在浮动元素的末尾添加一个空元素,设置 clear:both属性,after伪元素其实也是通过 content 在元素的后面生成了内容为一个点的块级元素;
其二,通过设置父元素 overflow。
面试的时候的时候面试官跟想听到伪类的方法
2、说说flex布局
内容太多,彻底学习去这里:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
-
面试重点回答需要知道这些,平时开发这些用的的最多
怎么横向居中?justify-content-属性定义了项目在主轴上的对齐方式。
.box { justify-content: flex-start | flex-end | center | space-between | space-around; }
怎么竖向居中?align-items-属性定义项目在交叉轴上如何对齐。
.box { align-items: flex-start | flex-end | center | baseline | stretch; }
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box { align-content: flex-start | flex-end | center | space-between | space-around | stretch; }
3、垂直居中的方法
- margin:0 auto;
- justify-content: center;
- text-algin:center
4、水平居中的方法
- flex布局的align-items: center或者margin:auto;
- position: absolute;top: calc( 50% -需要居中的一般高度);
平时用的一些小技巧样式(项目一定会用到但用的很少,还不能忘)
1、p标签段落前面缩进
p{text-indent:2em}
2、ul去掉前面的点
ul{list-style:none}
关于JS的面试题(持续更新中。。。)
1、数据类型和引用类型/javascript的typeof返回哪些数据类型,参考地址
- 基本数据类型:Number、String、Boolean、Null、 Undefined、Symbol(ES6),这些类型可以直接操作保存在变量中的实际值。
- 引用数据类型:Object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)
2、JS中深克隆和浅克隆详解,参考地址
- 浅复制(浅克隆):直接将存储在栈中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址
- 深复制(深克隆):就是把数据赋值给对应的变量,从而产生一个与源数据不相干的新数据(数据地址已变化)。深拷贝,是拷贝对象各个层级的属性
2.1浅克隆
- 1.基本数据类型的赋值(以String为例)
let a = "hello world"; let b = a; alert( b ); // 'hello world' a = "changed"; alert( b ); // 'hello world' // 在这段代码中,把a赋值给b,当a的值发生变化时,并不影响b
- 2引用数据类型的赋值(以Array为例)
let arr1 = [1, 2, 3, 4]; let arr2 = arr1; console.log( arr2 ); // [10, 2, 3, 4] arr1[0] = 10; console.log( arr2 ); // [10, 2, 3, 4] // 在这段代码中,把arr1赋值给arr2,当arr1的值改变时,arr2对应的值也会改变
对以上两个例子的分析
对于基本数据类型而言,把a的值赋值给b后,a的修改,不会影响到b
对于引用数据类型而言,把arr1赋值给arr2后,arr1的修改,会影响到arr2对应的值
基本数据类型是直接存储在 栈内存 中的,而引用数据类型,则仅仅是把地址存储在 栈内存 中,真正的数据是存储在 堆内存 中的,赋值操作时,仅仅把地址进行了赋值。
2.2 实现深克隆的方式
-
方法一: 递归
function deepClone( obj ){ let objClone = Array.isArray(obj) ? [] : {}; if( obj && typeof obj==="object"){ for(key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key]&&typeof obj[key] ==="object"){ objClone[key] = deepClone(obj[key]); }else{ objClone[key] = obj[key]; } } } } return objClone; } let a=[1,2,[2, 3],4], b=deepClone(a); a[2][0]=10; console.log(a,b);
-
方法二: JSON.stringify 和 JSON.parse
function deepClone(obj){ let _obj = JSON.stringify(obj), objClone = JSON.parse(_obj); return objClone } let a=[0,1,[2,3],4], b=deepClone(a); a[0]=1; a[2][0]=1; console.log(a,b);
-
方法三: jQuery中的 $.extend
let a=[0,1,[2,3],4], b=$.extend(true,[],a); a[0]=1; a[2][0]=1; console.log(a,b);
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。 -
方法四:var newArray = Array.slice(0) 用来生成新得数组
这个是vue源码中生成新数组的方法,偷偷学到的
3、js 宏任务和微任务,参考地址
宏任务(macrotask )和微任务(microtask )
macrotask 和 microtask 表示异步任务的两种分类。
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。
把下面的代码运行一下,加速你的理解:
//主线程直接执行
console.log('1');
//丢到宏事件队列中
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
//微事件1
process.nextTick(function() {
console.log('6');
})
//主线程直接执行
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
//微事件2
console.log('8')
})
//丢到宏事件队列中
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
4、重写js push函数(因为vue2.+的object.defineproperty中重写了push、pop、unshift、shift、reverse、sort)
let _push = Array.prototype.push
Array.prototype.push = function(){
for(let i of arguments){
_push.call(this, i);
}
// _push.call(this, arguments);
// console.log('参数为', arguments);
console.log('this', this);
}
let a = [1,2,3]
a.push(4,5)
5、this(this的4种指向和改变this指向的方式),参考地址和apply、call、bind区别、用法,参考地址
6、从输入URL到页面呈现的过程,参考地址
7、split() join() 的区别
- 前者是将字符串切割成数组的形式,后者是将数组转换成字符串
8、数组方法pop() push() unshift() shift()
- push()尾部添加 pop()尾部删除 unshift()头部添加 shift()头部删除
9、闭包是什么,有什么特性,对页面有什么影响
- 闭包就是能够读取其他函数内部变量的函数,使得函数不被GC回收,如果过多使用闭包,容易导致内存泄露
10、如何阻止事件冒泡
- ie:阻止冒泡ev.cancelBubble = true;非IE ev.stopPropagation();
11、如何阻止默认事件
- (1)return false;(2) ev.preventDefault();
12、事件委托是什么
- 利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!
13、Javascript的事件流模型都有什么?
-
“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
-
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
-
“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
14、回答以下代码,alert的值分别是多少?
<script>
var a = 100;
function test(){
alert(a);
a = 10; //去掉了var 就变成定义了全局变量了
alert(a);
}
test();
alert(a);
</script>
正确答案是: 100, 10, 10
15、判断 js 类型的方式
-
1、typeof
可以判断出’string’,‘number’,‘boolean’,‘undefined’,‘symbol’
但判断 typeof(null) 时值为 ‘object’; 判断数组和对象时值均为 ‘object’ -
2、instanceof
原理是 构造函数的 prototype 属性是否出现在对象的原型链中的任何位置function A() {} let a = new A(); a instanceof A //true //因为 Object.getPrototypeOf(a) === A.prototype;
-
- Object.prototype.toString.call()
常用于判断浏览器内置对象,对于所有基本的数据类型都能进行判断,即使是 null 和 undefined
- Object.prototype.toString.call()
-
- Array.isArray()
用于判断是否为数组
- Array.isArray()
16、统计字符串中字母个数
var str = "I think javascript is good";
//解:方法不唯一
str = str.toLowerCase();
var result = {};
for(var i in str) {
if(str[i] in result) {
result[str[i]]++;
} else {
result[str[i]] = 1;;
}
}
17、给数组去重
var arrays = [1,2,3,2,4,6,5,7]
function unique (arrray) {
var result=[]
//请编程实现数组去重
return result;
}
//1.利用es6的set对象
result = [...new Set(array)];//[...new Set (array)]
//2.利用对象属性的唯一性
let obj = {};
for (let i of array) {
if (!obj[i]) {
result.push(i);
obj[i]=1;
}
}
//3.利用sort方法排序去重
var newarray = array.sort();
result = [newarray[0]];
var length = newarray.length;
for( var i = 1 ;i<length; i++) {
newarray[i] !== newarray[i-1] && result.push(newarray[i]);
}
//4.利用for...of+includes()循环
for(var i of array) {
!result.includes(i) && result.push(i);
}
//5.用filter结合indexOf
result = array;
return result.filter((item, index)=> {
return result.indexOf(item) === index
})
//6.利用双层for循环(6分)类似
var length = array.length;
for(var i =0; i<length; i++) {
var only = true;
for(var j =i+1; j<length; j++){
if(!only) continue;
if(array[i] == array[j]) only = false;
}
if(only) result.push(array[i]);
}
18、js中forEach,for in,for of循环的用法,参考地址
上一篇: js面试题