前端面试知识总结(2019-5-24)
HTML
<!DOCTYPE html>
- 定义:
DOCTYPE
标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD
)来解析文档。<!DOCTYPE>
声明必须是HTML
文档的第一行,位于<html>
标签之前 - 作用:避免浏览器的怪异模式,避免浏览器使用自己的怪异模式解析渲染页面,这样在所有的浏览器里显示的就都是一个样子了
- 定义:
HTML5
为什么只需要写<!DOCTYPE HTML>
HTML5
不基于SGML
,因此不需要对DTD
进行引用,但是需要doctype
来规范浏览器的行为(让浏览器按照它们应该的方式来运行)1
而HTML4.01
基于SGML
,所以需要对DTD
进行引用,才能告知浏览器文档所使用的文档类型1
标准模式与兼容模式各有什么区别?
- 标准模式的排版和
JS
运作模式都是以该浏览器支持的最高标准运行。 - 在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作
- 标准模式的排版和
CSS
一、盒模型
- 本质就是一个盒子,它包括的内容从内到外依次是:实际内容,内边距,边框,外边距,在
chrome
中展示如图所示:
- 当我们设置一个元素的宽高时候,其实设置的是它的实际内容大小,它实际占用的宽高还需要加上内边距,边框,和外边距,如上图所示中的实际宽度为
450px
(300+50+50+50) 外边距合并(叠加):两个或多个块级盒子的垂直相邻边界会重合,它们的边界宽度是相邻边界宽度中的最大值,发生边距重叠的三种情况:父子元素边距重叠,兄弟元素边距重叠,空元素边距重叠,具体参见博客
边距重叠与BFC需要注意的是:只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并,另外水平边距是不会发生重叠的。
原因是如果块元素的 margin-top 与它的第一个子元素的margin-top 之间没有 border、padding、inline content、 clearance 来分隔,或者块元素的 margin-bottom 与它的最后一个子元素的margin-bottom 之间没有 border、padding、inline content、height、min-height、 max-height 分隔,那么外边距会塌陷。子元素多余的外边距会被父元素的外边距截断。
BFC:全称为
Block Formatting Context
,即块级格式化上下文,用于解决边距重叠的问题。创建BFC
的方法:浮动(float
的值不为none
);绝对定位元素(position
的值为absolute
或fixed
);行内块(display
为inline-block
);表格单元(display
为table
、table-cell
、table-caption
等HTML
表格相关属性);弹性盒(display
为flex
或inline-flex
);overflow
不为visible
;css reset
:用于改写HTML
标签的默认样式。有些HTML标签在浏览器里有默认的样式,例如p
标签有上下边距,li
标签有列表标识符号等。这些默认样式在不同浏览器之间也会有差别。这必然会带来浏览器兼容问题。因此,可以使用CSS
代码去掉这些默认样式,从而覆盖浏览器的CSS默认属性。box-sizing
:它有如下几种属性content-box
,默认值,可以使设置的宽度和高度值应用到元素的内容框。盒子的width
只包含内容border-box
, 设置的width
值其实是除margin
外的border+padding+element
的总宽度inherit
, 规定应从父元素继承box-sizing
属性的值- 全局设置
border-box
很好,首先它符合直觉,其次它可以省去一次又一次的加加减减,而且让有边框的盒子正常使用百分比宽度
另外补充用
div
画三角形1
2
3
4
5
6
7
8<style>
.triangle {
width : 0;
height: 0;
border : 100px solid transparent;/*设置border为透明*/
border-top : 100px solid blue;
}
</style>
二、flex布局(弹性盒子布局)
- 布局的传统解决方案是:
display
(设置行内\块级属性或flex布局),position
(设置绝对定位,相对定位或默认定位)和float
(浮动)属性 flex
布局是什么:任何容器都可以指定为flex
布局,行内元素也可以,但是设为flex
布局之后,子元素的float
,clear
,vertical-align
属性将失效- 基本概念:在
flex
布局中,分为容器和容器中的项目,容器默认存在两根轴,水平的主轴main axis
,和垂直的交叉轴cross axis
。描述单个项目占据的大小的参数:main size
和cross size
容器的属性:
flex-direction:描述项目子元素的垂直分布或水平分布
1
2
3
4
5<style>
.box {
flex-direction: row | row-reverse | column | column-reverse;/*水平|反向水平|垂直|反向垂直*/
}
</style>flex-wrap:描述子元素是否换行
1
2
3
4
5<style>
.box {
flex-wrap: nowrap | wrap | wrap-reverse;/*不换行|换行|反向换行*/
}
</style>注意:如果不换行,有可能造成子元素原有的宽度发生变化,在换行或反向换行时,子元素的宽度为设置的值
flex-flow:是
flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
justify-content: 描述子元素在水平方向的对齐方式
1
2
3
4
5<style>
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;/*左对齐|右对齐|居中|两端对齐项目等距|项目两侧间隔相等*/
}
</style>align-items:描述子元素在垂直方向的对齐方式
1
2
3
4
5<style>
.box {
align-items: flex-start | flex-end | center | baseline | stretch;/*上对齐|下对齐|居中|第一行文字对齐|未设置高度时充满容器*/
}
</style>align-content:描述多根水平轴线在交叉轴方向的对齐方式。只有一根轴线不起作用。
1
2
3
4
5<style>
.box {
align-content: flex-start | flex-end | center | space-between | space-around |stretch;/*同水平方式*/
}
</style>
项目的属性
order:描述项目的排列顺序,数值越小,越靠前,默认为
0
1
2
3
4
5<style>
.item {
order: <integer>;
}
</style>flex-grow:定义项目的放大比例,默认为
0
(即使有剩余空间也不放大)1
2
3
4
5<style>
.item {
flex-grow: <number>;
}
</style>flex-shrink:定义项目的缩小比例,默认为
1
(即使空间不足也不会缩小)1
2
3
4
5<style>
.item {
flex-shrink: <number>;
}
</style>flex-basis:定义在分配剩余空间之前,项目占据的主轴空间(
main size
),默认值是项目本来的大小,它可以设为跟width
或height
属性一样的值1
2
3
4
5<style>
.item {
flex-basis: <length>;
}
</style>flex:是
flex-grow
,flex-shrink
,flex-basis
的简写,默认值是0 1 auto
align-self:允许单个项目与其他项目不同的垂直方向的对齐方式,可以覆盖
align-items
属性,默认值为auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
1
2
3
4
5<style>
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
</style>
flex布局实战:利用flex布局写的筛子
三、CSS居中
- 块级元素与行内元素:
h1
,div
,p
,table
,表单,列表,行内元素有a
,img
,input
,lable
,块级元素与行内元素转换用display
属性,块级元素设为block
,行内元素设为inline
。由于行内元素无法设置宽高,因此,如果想要既是行内元素又能设置宽高可以将display
值设为inline-block
块级元素水平居中:
设置外边距
1
2
3
4
5<style>
.box {
margin: 0 auto;
}
</style>绝对定位+负边距(父元素position非static)
1
2
3
4
5
6
7<style>
.box {
position: absolute;
left:50%;
margin-left: -50px; /*这里的值是这个元素的宽度的一半*/
}
</style>弹性盒子布局(具体参考第二部分)
块级元素垂直居中
绝对定位+负边距(父元素position非static)
1
2
3
4
5
6
7<style>
.box {
position: absolute;
top: 50%;
margin-top: -175px; /*这里的值是元素高度的一半*/
}
</style>绝对定位+父元素position非static+子元素transform
1
2
3
4
5
6
7
8
9
10<style>
.outside {
position: relative; /*父元素非static*/
}
.inner {
position: absolute;
top:50%;
transform: translateY(-50%); /*相对于自身高度,向上移动50%*/
}
</style>弹性盒子布局(具体见第二部分)
行内元素居中:
vertical-align
:用于图片相对于文字的中心轴线居中text-align
:仅用于文本的水平居中line-height
: 可用于文本的垂直居中,这个属性描述的是行高,把一段文本的line-height
设为父元素的高度就可以垂直居中- 图片在一个div中的居中可以用到绝对定位居中和弹性盒子居中,垂直水平都可以,用法同块级元素
关于
position
其中有几点需要注意:- 默认值是
static
这个时候,如果其子元素想利用外边距取负值的方法居中的时候,就不会达到想要的效果,这个时候需要个想要居中的元素的父元素position
赋值为非static
即可 - 当一个元素有属性
z-index
时候,另外需要给它的position
赋值为absolute
- 默认值是
四、css其他几种布局方式
- 栅格布局(百分比)
- 格子布局(grid)见实战基本网格平均布局(适配手机)
- 圣杯布局
- 响应式布局:可以运用以上布局方式进行响应式布局
五、其他
- px,em,rem的区别?具体见菜鸟教程
JS
一、基础知识
- JS中的数据类型:js数据类型分为基本类型和引用类型,两者最主要的区别在于复制方面,前者是直接深复制,后者是类指针的引用类型,即浅复制。基本类型有
null
,undefine
,number
,string
,boolean
,symbol
,引用类型object
,具体细分有Array
,Date
,RegExp
,Function
等等,比较特殊的一点就是还存在基本包装类型(因为他们还是遵循浅复制的原则),他们既是基本类型,但是又存在类似引用的方法。- null:表示一个空对象指针
- undefined: 未初始化的变量
- number:包括
NaN
,需要掌握数值转换的几种方法:Number()
,parseInt()
,parseFloat()
- string: 需要掌握转换字符串方法
toString()
- boolean:只有两个字面值
true
和false
,其他所有类型的值都与这两个boolean
等价,需要调用转型函数Bollean()
,需要注意的是各种数据类型对应的转换规则 - symbol:直接使用
Symbol()
创建新的symbol
类型,并用一个可选的字符串作为其描述,注意字符串相同的两个变量不是全等的
类型判断的几种方法
typeof操作符
1
2
3
4var message = "some string";
console.log(typeof message);//"string"
console.log(typeof(message));//"string"
console.log(typeof 95);//"number"数据类型 | typeof返回值
—|—
字符串、””、’’ | string
对象、null、数组、正则表达式、日期 | object
函数 | function
布尔值 | boolean
数值 | number
未定义变量 | undefinedArray.isArray()
1
2if (Array.isArray(value)){ //对数组执行某些操作
}Object.prototype.toString.call(value):传入参数是需要检测的目标,返回值是
[object type]
,其中type
取值可以是null
、string
、boolean
、number
、undefined
、array
、function
、object
、date
、math
1
2var message = "some string";
console.log(Object.prototype.toString.call(message));//[object String]
其他检测函数或操作符
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例 的原型中)是否存在,参数以字符串传入,返回布尔值
- isPrototypeOf(object):用于检查传入的对象的原型对象是否是调用该函数的对象,返回值为布尔值
instanceof 操作符:测试实例与原型链中出现过得构造函数,结果返回布尔值
1
2
3
4
5
6console.log(Object.prototype.isPrototypeOf(instance));//true
console.log(SuperType.prototype.isPrototypeOf(instance));//true
console.log(SubType.prototype.isPrototypeOf(instance));//true
console.log(instance instanceof Object);//true
console.log(instance instanceof SuperType);//true
console.log(instance instanceof SubType);//true
关于数组:
数组->字符串
1
2var colors = ["red", "blue", "green"];
console.log(colors.toString());//red,blue,green数组->特殊间隔的字符串
1
2
3var colors = ["red", "green", "blue"];
console.log(colors.join(",")); //red,green,blue
console.log(colors.join("||")); //red||green||blue字符串->数组
1
2
3
4var colorText = "red,blue,green,yellow";
var colors1 = colorText.split(",");//["red", "blue", "green", "yellow"]
var colors2 = colorText.split(",", 2);//["red", "blue"]
var colors3 = colorText.split(/[^\,]+/);//["", ",", ",", ",", ""]数组的栈方法(对数组的末位置操作)
1
2
3
4
5
6
7
8
9
10
11var colors = new Array();
var count = colors.push("red", "green");
console.log(count); //2
console.log(colors);//[ 'red', 'green' ]
count = colors.push("black");
console.log(count); //3
console.log(colors);//[ 'red', 'green', 'black' ]
var item = colors.pop();
console.log(item); //"black"
console.log(colors.length); //2
console.log(colors);//[ 'red', 'green' ]push向数组末尾增加值,返回值是修改后的数组的length,pop取出数组末尾的值,返回值是移除的项
数组的队列方法(对数组的首位置进行操作)
1
2
3
4
5var arr = [1, 2, 3, 4, 5]
console.log(arr.shift());//1
console.log(arr.length);//4
console.log(arr.unshift(6,7));//6
console.log(arr);//[ 6, 7, 2, 3, 4, 5 ]数组重排序
1
2
3
4
5
6
7
8
9
10
11
12//reverse
var values = [1, 2, 3, 4, 5];
values.reverse();
console.log(values);//5, 4, 3, 2, 1
//sort需要传入比较函数
var arr = [18, 12, 23, 4, 5, 26];
function compare (num1, num2) {
return num1 - num2;
}
arr.sort(compare);
console.log(arr); //[ 4, 5, 12, 18, 23, 26 ]连接数组
1
2
3
4var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yellow", ["black", "brown"]);
console.log(colors); //[ 'red', 'green', 'blue' ]
console.log(colors2); //[ 'red', 'green', 'blue', 'yellow', 'black', 'brown' ]删除数组中某些项(同字符串)
1
2
3
4
5var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice(1); //start
var colors3 = colors.slice(1,4); // start end
console.log(colors2); //[ 'green', 'blue', 'yellow', 'purple' ]
console.log(colors3); //[ 'green', 'blue', 'yellow' ]数组的删除插入和替换
1
2
3
4
5
6
7
8
9
10
11var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1);
console.log(colors);//[ 'green', 'blue' ]
console.log(removed); //[ 'red' ]
removed = colors.splice(1, 0, "yellow", "orange"); console.log(colors); //[ 'green', 'yellow', 'orange', 'blue' ]
console.log(removed); //[]
removed = colors.splice(1, 1, "red", "purple");
console.log(colors); //[ 'green', 'red', 'purple', 'orange', 'blue' ]
console.log(removed);//[ 'yellow' ]
原型链与继承
原型
原型就是包含特定类型的所有实例共享的方法和属性的对象。任何一个构造函数,不管是自定义的还是
js
已有的,他们都带有一个名为prototype
的属性,这个属性指向这种特定类型的原型对象,而这个原型对象又包含一个名为constructor
的属性,这个属性指向这种类型的构造函数。构造函数的实例对象也有一个指针指向原型对象名为[[prototype]]
,可以用Object.getPrototypeOf(obj)
获取原型链
即便自定义类型的构造函数有一个原型对象,但是终究还是指向
js
本就有的类型,比如Object
或Function
。这就是因为原型链的存在,因为某个特定类型的原型对象其实是另一个类型的实例,如此层层递进,就构成了实例与原型的链条⛓继承
由于原型链的存在,实例对象,可以继承到原型链上所有的属性和方法,但是不能忘记,所有的引用类型都继承了
Object
,而这个继承也是通过原型链实现的,所以默认的原型都会包含一个内部指针指向Object.prototype
。还有一点需要注意除了Object.prototype
和SuperType.prototype
其他类型的原型都没有constructor
属性
闭包
解释
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另一个函数。内部函数可以在外部函数的参数部分,函数体部分以及返回值部分
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function createcompare (propertyName) {
return function (obj1, obj2) {
var value1 = obj1[propertyName];
var value2 = obj2[propertyName];
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
}
var compare = createcompare("age");
console.log(compare({"age" : 2} , {"age" : 3}));实例:
见博客- 应用场景:迭代器,将变量存在内存中,与垃圾回收机制,内存销毁有关
call、apply与bind
- call与apply都是改变函数体内的
this
指向,用于在特定作用域调用函数。两者最明显的区别就是对于call
函数而言,第一个参数是this
,其余参数都是直接传给函数,而apply
第一个参数仍然是this
,但是其余参数以数组形式或arguments
传递。bind
方法创建一个新的函数,在调用时设置this
关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments);
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]);
}
function callSum3(num1, num2){
return sum.call(this, num1, num2);
}
console.log(callSum1(10,10)); //20
console.log(callSum2(10,10)); //20
console.log(callSum3(10,10)); //20
- call与apply都是改变函数体内的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
箭头函数
- 作用:更简短的函数,并且不用绑定
this
简短函数示例
1
2
3
4
5
6
7
8
9var arr = [1, 2, 3, 4];
var newarr = arr.map( function(element) {
return element += 1;
});
var newarr1 = arr.map((element) => { return element += 1})
var newarr2 = arr.map((element) => element += 1)
console.log(newarr);//[ 2, 3, 4, 5 ]
console.log(newarr1);//[ 2, 3, 4, 5 ]
console.log(newarr2);//[ 2, 3, 4, 5 ]
- 作用:更简短的函数,并且不用绑定
* 不绑定this示例
1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4];
var newarr = arr.map( function(element) {
return element += 1;
});
var newarr1 = arr.map((element) => { return element += 1})
var newarr2 = arr.map((element) => element += 1)
console.log(newarr);//[ 2, 3, 4, 5 ]
console.log(newarr1);//[ 2, 3, 4, 5 ]
console.log(newarr2);//[ 2, 3, 4, 5 ]
- 关于this
- 在严格模式下
this
为undefined
,在普通模式下this
指向window
- 对象方法调用用
this
指向调用调用对象 call
和apply
可以显示绑定this
指向- 在箭头函数中,
this
指向外层作用域的this
- 在严格模式下
Vue
计网
一、DNS
- 概述
DNS
是互联网的一项服务,它作为将域名和IP
相互映射的一个分布式数据库,使用户更方便得访问互联网- 由解析器和域名器组成
DNS
协议属于应用层协议,主要为其他应用协议服务,而不是直接面向用户。
- dns系统的层次结构:根域 > 顶级域(一级域)> 二级域等等如下图所示:
- 域名服务器:能提供域名解析的服务器,分为顶级域名服务器、权威域名服务器、本地域名服务器。域名服务器上记录的类型可以是
A
,NS
,MX
,CNAME
需要注意的是,本地域名服务器不属于服务器的层次结构,每个ISP都有一个本地DNS服务器,当主机发出DNS请求时,该请求被发往本地DNS服务器。它起着代理的作用,转发请求到层次结构中。
* A:`address`,用户可以在这里设置子域名并指向自己目标主机上,从而通过域名找到服务器,还可以实现:泛域名解析(将该域名的子域名都指向同一个空间)、负载均衡(当相同子域名有多个目标地址时,表示轮询,可以达到负载均衡的目的,但需要虚拟主机服务商支持)
* CNAME:别名指向可以为一个主机设置别名。目标主机地址只能使用主机名,不能使用`IP`地址。`A`是优先于`CNAME`的
* MX:邮件交换记录,用于将以该域名为结尾的电子邮件指向对应的邮件服务器进行处理
* NS:记录从哪个`dns`服务器可以获得某个域的`dns`记录,即用于记录查询链
- dns提供的服务:映射域名与
IP
地址,并提供别名;为邮件服务器提供别名;负载分配(一个域名多个IP
的时候) - dns域名解析过程
- dns正向解析:分为递归查询(主机向本地服务器的查询,由请求的服务器直接返回权威答案)和迭代查询(由本地服务器逐步向各层服务器的查询过程)
- dns反向解析:在域名系统中,一个
IP
地址可以对应多个域名,因此从IP
出发去找域名,理论上应该遍历整个域名树,但是在Internet
中不是这样实现的。为了完成逆向域名解析,系统提供一个特别域,该特别域成为逆向解析域in-addr.arpa
。这样欲解析的IP
地址就会被表达成一种像域名一样的可显示串形式,后缀以逆向解析域域名in-addr.arpa
结尾 - dns缓存:先在本地缓存中查找若没有,查找
hosts
文件,若还是没有,则像ns
服务器发出请求,查询ns
的缓存。缓存时间TTL
是对象的服务器定义的
dns记录与报文:
- dns记录由四个部分组成:
type
(标志这是一条什么记录),value
(Name
的对应值),Name
(Value
的对应值),TTL
(本记录应该在缓存中呆多久) dns报文:如下图所示
- dns记录由四个部分组成:
- dns的安全性:dns大多数情况下是安全的
- 对于
DDos
攻击,dns有包过滤系统和缓存服务,仅在DDos
攻击指向顶级服务器的时候稍微有些困扰 - 可以被中间人攻击(伪造回答哄骗客户主机)和dns毒害攻击(伪造回答哄骗下一级dns服务器来缓存,从而欺骗客户主机)但是技术上很难实现
- dns服务器本身可被利用与攻击其他服务器,但是至今只是个例
- 对于
二、HTTP
- 一些web术语和基本概念、约定:web文档是由对象组成的,一个对象就是一个文件,对象一般由
url
定位。url
由两部分组成,一部分是主机名,另一部分是对象的路径名 - 概况:
http
一般使用tcp
作为传输层协议(但http
协议中并没有规定必须使用它说)
三、TCP
四、cookie和session
五、缓存的实现方式
六、浏览器中输入一个url之后会发生什么事情
具体见博客SAP电话面试总结问题四
七、关于跨域
GIT
问题
- 闭包就是内部函数可以访问外部函数参数吗?那不一定非要放在返回值里面啊,放在函数体里面也可以啊,那放在参数里面可以吗