前端面试资料总结(持续更新)
CSS盒模型
盒模型包含了content,padding,border,margin
1.一个是标准模型:盒模型的宽高只是content的宽高
2.一个是IE模型(又叫怪异模型):盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高。
如何统一模型:将模型的宽高都统一为内容(content)+填充(padding)+边框(border)的总宽高。
div{
box-sizing: border-box;
}
两种盒模型
DOM事件流
JS中事件分为三个阶段: 事件捕获 --> 事件目标 --> 事件冒泡
栗子:给目标元素(text)绑定click事件,实际的(text)元素在捕获阶段不会接收到事件,意味着在捕获阶段,事件从document到<body>再到<div>后就停止了。下一个阶段是“处于目标阶段”,于是事件在(text)上发生,并在事件处理中被看成是冒泡阶段的一部分。最后,冒泡阶段发生,事件又传播回文档。
DOM层级越小,事件传播的消耗越小,在一定情况下也可以视为一种优化性能的手段
比较常见的冒泡现象:
<a href="http://www.sina.com" id='test'>sina</a></body>
<script>
document.onclick = function() {
alert('doc click');
return false;
}
var a = document.getElementById('test');
a.onclick = function() {
alert('a click');
}
</script>
正常执行顺序
1.从document慢慢找下去,判断当前元素是否是时间的触发源
2.找到事件源,执行a元素上的onclick事件
2.事件进入冒泡阶段,包含a元素的document的onclick事件
3.事件完成,进入浏览器默认行为,即跳转。
PS:如果当使用return false会打断后续行为,所以这里不会跳转。
使用event.preventDefault
取消浏览器默认行为
使用event.stopPropagation
会取消冒泡,但不取消浏览器默认行为。
CSS层叠规则(视图上的显示层级)
显示的层级元素居中
-
水平居中
行内元素:text-align: center
块级元素:margin: 0 auto
absolute + transform
flex + justify-content: center
-
垂直居中
line-height: height
absolute + transform
flex + align-items: center
table
-
水平垂直居中
absolute + transform
flex + justify-content + align-items
CSS选择器问题
优先级:!important > 行内样式 > #id > .class > tag > * > 继承 > 默认
css选择器原理:采用递归方式,从右往左找,如body #box1 .box2 div span a
,
1.浏览器会先找所有的a
标签
2.从这些a
标签中找到父元素是span
的
3.从这些span
中找父元素是div
的
4.从这些div
中找父元素是.box2
的
........
优化问题:
1.层级越多需要找的时间越久,耗时,尽量直接写class或者id来找,层级顶多3层。
2.尽量不要直接写div span a
,因为页面上可能有很多a
标签,span
和div
,会更耗时。
清除浮动
只介绍以下两种我用的,其他不赘述
1.(推荐)给浮动元素的父元素加上clearfix
类
.clearfix{*zoom:1;}
.clearfix:after{display:block; content:"clear"; height:0; clear:both; overflow:hidden; visibility:hidden;}
2.给浮动元素结尾处添加一个空的div
,并且clear:both;
link 与 @import 的区别
1.link功能较多,可以定义 RSS,定义 Rel 等作用,而@import只能用于加载 css
2.当解析到link时,页面会同步加载所引的 css,而@import所引用的 css 会等到页面加载完才被加载,从体验来说,link要由于@import
3.@import需要 IE5 以上才能使用
4.link可以使用 js 动态引入,@import不行
javascript数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
区别:
1.值类型变量是存放在栈区的(栈区指内存里的栈内存)
2.引用类型顾名思义只是引用,数据是存在堆内存中,如果内存中的值变化,那么引用它的变量也会变化
看下面栗子
var a = [1,2,3];
var b = a;
a.push(4);
console.log(b); // [1,2,3,4]
关于变量提升问题
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。来看这一段代码
console.log(a,fun); // undefiend undefiend
var a = 1;
function fun(){}
那么,JS执行以上代码时,实际执行顺序是这样的
var a, fun;
console.log(a,fun);
a = 1;
fun = function (){}
闭包
script标签
1.<script defer>
: 异步加载,元素解析完成后执行
2.<script async>
: 异步加载,与元素渲染并行执行
对于大多情况来说,script标签尽量放在html最底部引入进来,防止影响html以及css的加载,影响页面呈现的速度。
对象的深拷贝浅拷贝问题
讲一下简单实现原理
1.浅拷贝:便利对象source
的属性,然后赋值到新对象target
上,如果source
的某一个子属性是引用类型
的,那么target
复制的属性的内存地址与source
的的子属性指向同一内存地址。会出现如下问题:
//浅拷贝
function shallow(target, source) {
for (let i in source) {
target[i] = source[i];
}
return target;
}
var obj1 = {
name: 'obj1',
arr: [1, 2, 3]
},
obj2 = {};
//浅拷贝一次
shallow(obj2, obj1);
obj1.arr.push(4);
console.log(obj2.arr); // [1,2,3,4]
2.深拷贝:在浅拷贝基础上,遇到引用类型的值需要再次执行浅拷贝,也就是递归执行浅拷贝
,就不会出现浅拷贝的问题
function deep(target, source) {
for (var i in source) {
// 含有引用类型
if (typeof source[i] === 'object') {
// 这里可能是数组或者对象
if (source[i].constructor == Array) {
target[i] = [];
} else {
target[i] = {};
}
//需要递归执行deep拷贝
deep(target[i], source[i]);
} else {
target[i] = source[i];
}
}
}
var obj1 = {
name: 'obj1',
arr: [1, 2, 3]
},
obj2 = {};
//浅拷贝一次
deep(obj2, obj1);
obj1.arr.push(4);
console.log(obj1.arr,obj2.arr); // [1,2,3,4] [1,2,3]
对于更多出现的情况请参考lodash拷贝
new到底干了什么
1.新生成一个对象obj
2.链接到原型: obj.__proto__ = 对应的构造函数.prototype
3.修改this执行: apply
4.返回新对象