有朋友准备看看新工作,正好有空,帮忙整理了一下常见的前端面试题,整理的面试题都比较基础,主要面向初中级前端。篇幅有限,有些知识就直接贴文章链接了,大家可以自己去看~
BFC(Block Formatting Context)格式化上下文,是 Web 页面中盒模型布局的 CSS 渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。
形成 BFC 的条件
BFC 的特性
CSS3中的盒模型有以下两种:标准盒子模型、IE盒子模型
盒模型都是由四个部分组成的,分别是margin、border、padding和content。
在标准盒模型性中
盒子在网页中实际占用:
宽=width + padding2 + border2 + margin2
高=height + padding2 + border2 + margin2
盒模型实际大小:
宽=width + padding2 + border2
高=height + padding2 + border2
在IE盒模型性中
盒子在网页中实际占用:
宽=width + margin2
高=height + margin2
盒模型实际大小:
宽=width
高=height
可以通过修改元素的box-sizing属性来改变元素的盒模型:
当需要垂直居中的元素高度未知时,一般采用一下几种方案实现垂直居中:
使用绝对定位和transform
css复制代码.parent {
position: relative;
width: 100%;
height: 400px;
}
.children {
position: absolute;
top: 50%;
transform: translate(0, -50%);
}
flex实现垂直居中(最常用的)
css复制代码.parent {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 400px;
background: #fff;
}
.children {
background: red;
}
通过table属性
css复制代码<div class="parent">
<div class="children">
<div>test</div>
</div>
</div>
.parent {
display: table;
text-align:center;
}
.children {
background: #ccc;
display: table-cell;
vertical-align: middle;
}
.child div {
width: 300px;
height: 150px;
background: red;
margin: 0 auto;
}
预处理器:例如LESS、Sass、Stylus,用来预编译Sass或less,增强了css代码的复用性,还有层级、mixin、变量、循环、函数等,具有很方便的UI组件模块化开发能力,极大的提高工作效率。
后处理器:例如PostCSS,通常被视为在完成的样式表中根据CSS规范处理CSS,让其更有效;目前最常做的是给CSS属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。
CSS 预处理器为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题”,例如你可以在 CSS 中使用变量、简单的逻辑程序、函数(如右侧代码编辑器中就使用了变量$color)等等在编程语言中的一些基本特性,可以让你的 CSS 更加简洁、适应性更强、可读性更佳,更易于代码的维护等诸多好处。
问题描述: 两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向。
计算原则: 折叠合并后外边距的计算原则如下:
解决办法: 对于折叠的情况,主要有两种:兄弟之间重叠和父子之间重叠
(1)兄弟之间重叠
(2)父子之间重叠
flex知识点的话,建议大家去看阮一峰老师的文章,看完应该就明白了
Flex 布局教程:语法篇
Flex 布局教程:实例篇
@media媒体查询是针对不同的媒体类型定义不同的样式,特别是响应式页面,可以针对不同屏幕的大小,编写多套样式,从而达到自适应效果,代码如下:
css复制代码@media screen and (max-width: 720px) {
body {
background-color: #6633FF;
}
}
@media screen and (max-width: 640px) {
body {
background-color: #00FF66;
}
}
/*
上述的代码分别对分辨率在0~640px以及640px~720px的屏幕设置了不同的背景颜色。
*/
rem 是一个灵活的可扩展的单位,由浏览器转化像素并显示。与em单位不同,rem单位无论嵌套层级如何,都只相对于浏览器的根元素(HTML元素)的font-size
由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport, 代码如下:
js复制代码(function flexible (window, document) {
var docEl=document.documentElement
var dpr=window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize=(12 * dpr) + 'px'
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem=viewWidth / 10
function setRemUnit () {
var rem=docEl.clientWidth / 10
docEl.style.fontSize=rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >=2) {
var fakeBody=document.createElement('body')
var testElement=document.createElement('div')
testElement.style.border='.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight===1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
什么是vw/vh ?
vw/vh是一个相对单位(类似于em,rem)
相对视口的尺寸计算结果
1px的问题经常出现在移动端边框设置上,会导致设置1px边框看起来较粗,影响用户体验,对于boder的1px问题,可以通过伪元素 + transform来解决, 代码如下:
css复制代码/* 手机端实现真正的一像素边框 */
.border-1px,
.border-bottom-1px,
.border-top-1px,
.border-left-1px,
.border-right-1px {
position: relative;
}
/* 线条颜色 */
.border-1px::after,
.border-bottom-1px::after,
.border-top-1px::after,
.border-left-1px::after,
.border-right-1px::after {
background-color: #000;
}
/* 底边边框一像素 */
.border-bottom-1px::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
transform-origin: 0 0;
}
/* 上边边框一像素 */
.border-top-1px::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
transform-origin: 0 0;
}
/* 左边边框一像素 */
.border-left-1px::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 1px;
height: 100%;
transform-origin: 0 0;
}
/* 右边边框1像素 */
.border-right-1px::after {
content: "";
position: absolute;
right: 0;
top: 0;
width: 1px;
height: 100%;
transform-origin: 0 0;
box-sizing: border-box;
}
/* 边框一像素 */
.border-1px::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 1px solid gray;
box-sizing: border-box;
}
/* 设备像素比 */
/* 显示屏最小dpr为2 */
@media (-webkit-min-device-pixel-ratio: 2) {
.border-bottom-1px::after, .border-top-1px::after {
transform: scaleY(0.5);
}
.border-left-1px::after, .border-right-1px::after {
transform: scaleX(0.5);
}
.border-1px::after {
width: 200%;
height: 200%;
transform: scale(0.5);
transform-origin: 0 0;
}
}
/* 设备像素比 */
@media (-webkit-min-device-pixel-ratio: 3) {
.border-bottom-1px::after, .border-top-1px::after {
transform: scaleY(0.333);
}
.border-left-1px::after, .border-right-1px::after {
transform: scaleX(0.333);
}
.border-1px::after {
width: 300%;
height: 300%;
transform: scale(0.333);
transform-origin: 0 0;
}
}
iOS 11
css复制代码padding-top: constant(safe-area-inset-top);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
padding-left: constant(safe-area-inset-left);
iOS 11.2+
css复制代码padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
如果图片设置的是背景图
css复制代码background-size: cover;
如果是img标签图片
css复制代码object-fit: cover;
可参考:常见的CSS布局
JavaScript一共有8种数据类型
七种基本数据类型:Undefined、Null、Boolean、Number、String、Symbol(es6新增)和BigInt(es10新增)
一种复杂数据类型:Object 里面包含 Function、Array、Date等
typeof
js复制代码/*
优点:能够快速区分基本数据类型
缺点:不能将Object、Array和Null区分,都返回object
*/
console.log(typeof 1); // number
console.log(typeof NaN); // number
console.log(typeof true); // boolean
console.log(typeof 'mc'); // string
console.log(typeof Symbol) // function
console.log(typeof function(){}); // function
console.log(typeof console.log()); // function
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object
console.log(typeof undefined); // undefined
instanceof
js复制代码/*
优点:能够区分Array、Object和Function,适合用于判断自定义的类实例对象
缺点:Number,Boolean,String基本数据类型不能判断
*/
console.log(1 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log(function(){} instanceof Object); // true
console.log({} instanceof Function); // false
console.log({} instanceof Object); // true
js复制代码/*
优点:精准判断数据类型
缺点:写法繁琐不容易记,推荐进行封装后使用
*/
const toString=Object.prototype.toString;
console.log(toString.call(1)); // [object Number]
console.log(toString.call(true)); // [object Boolean]
console.log(toString.call('mc')); // [object String]
console.log(toString.call([])); // [object Array]
console.log(toString.call({})); // [object Object]
console.log(toString.call(function(){})); // [object Function]
console.log(toString.call(undefined)); // [object Undefined]
console.log(toString.call(null)); // [object Null]
js复制代码function instanceOf(left, right) {
let proto=left.__proto__
let prototype=right.prototype
while (true) {
if (proto===null) return false
if (proto===prototype) return true
proto=proto.__proto__
}
}
除了es6的new Set()去重外,可以通过以下几种方法实现数组去重
js复制代码// 利用filter去实现
Array.prototype.unique1=function() {
return this.filter((item, index, array)=> {
return this.indexOf(item)===index;
});
}
js复制代码Array.prototype.unique2=function() {
const n={}, r=[]; // n为hash表,r为临时数组
for (let i=0; i < this.length; i++) {
if (!n[this[i]]) { // 如果hash表中没有当前项
n[this[i]]=true; //存入hash表
r.push(this[i]); //把当前数组的当前项push到临时数组里面
}
}
return r;
}
js复制代码// 返回后的数组顺序会乱
Array.prototype.unique3=function() {
this.sort();
const r=[this[0]];
for (let i=1; i < this.length; i++) {
if (this[i] !==this[i - 1]) {
r.push(this[i]);
}
}
return r;
}
执行上下文(以下简称“上下文”)的概念在 JavaScript 中是颇为重要的。变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。每个上下文都有一个关联的变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。虽然无法通过代码访问变量对象,但后台处理数据会用到它。
全局上下文是最外层的上下文。根据 ECMAScript 实现的宿主环境,表示全局上下文的对象可能不一 样。在浏览器中,全局上下文就是我们常说的window对象,因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法。使用 let 和 const 的顶级声明不会定义在全局上下文中,但在作用域链解析上效果是一样的。上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。
每个函数调用都有自己的上下文。当代码执行流进入函数时,函数的上下文被推到一个上下文栈上。 在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。ECMAScript 程序的执行流就是通过这个上下文栈进行控制的。
上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域链的最前端。如果上下文是函数,则其活动对象(activation object)用作变量对象。活动对象最初只有一个定义变量:arguments。(全局上下文中没有这个变量。)作用域链中的下一个变量对象来自包含上下文,再下一个对象来自再下一个包含上下文。以此类推直至全局上下文;全局上下文的变量对象始终是作用域链的最后一个变量对象。
代码执行时的标识符解析是通过沿作用域链逐级搜索标识符名称完成的。搜索过程始终从作用域链 的最前端开始,然后逐级往后,直到找到标识符。(如果没有找到标识符,那么通常会报错。) 看一看下面这个例子:
js复制代码var color="blue";
function changeColor() {
if (color==="blue") {
color="red";
} else {
color="blue";
}
}
changeColor();
对这个例子而言,函数 changeColor()的作用域链包含两个对象:一个是它自己的变量对象(就 是定义 arguments 对象的那个),另一个是全局上下文的变量对象。这个函数内部之所以能够访问变量color,就是因为可以在作用域链中找到它。
此外,局部作用域中定义的变量可用于在局部上下文中替换全局变量。看一看下面这个例子:
js复制代码var color="blue";
function changeColor() {
let anotherColor="red";
function swapColors() {
let tempColor=anotherColor;
anotherColor=color;
color=tempColor;
// 这里可以访问 color、anotherColor 和 tempColor
}
// 这里可以访问 color 和 anotherColor,但访问不到 tempColor
swapColors();
}
// 这里只能访问 color
changeColor();
以上代码涉及 3 个上下文:全局上下文、changeColor()的局部上下文和 swapColors()的局部 上下文。全局上下文中有一个变量 color 和一个函数 changeColor()。changeColor()的局部上下文中有一个变量 anotherColor 和一个函数 swapColors(),但在这里可以访问全局上下文中的变量 color。swapColors()的局部上下文中有一个变量 tempColor,只能在这个上下文中访问到。全局上下文和changeColor()的局部上下文都无法访问到 tempColor。而在 swapColors()中则可以访问另外两个 上下文中的变量,因为它们都是父上下文。下图展示了这个例子的作用域链。
上图中的矩形表示不同的上下文。内部上下文可以通过作用域链访问外部上下文中的一切,但外 部上下文无法访问内部上下文中的任何东西。上下文之间的连接是线性的、有序的。每个上下文都可以到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索。swapColors()局部上下文的作用域链中有 3 个对象:swapColors()的变量对象、changeColor()的变量对象和全局变量对象。swapColors()的局部上下文首先从自己的变量对象开始搜索变量和函数,搜不到就去搜索上一级变量对象。changeColor()上下文的作用域链中只有 2 个对象:它自己的变量对象和全局变量对象。因此,它不能访问 swapColors()的上下文。
闭包是指有权访问另外一个函数作用域中的变量的函数,有兴趣的可以看看几篇文章,看完会又更深刻的理解
破解前端面试(80% 应聘者不及格系列):从闭包说起
call/apply/bind都是用来修改this指向的
apply 和 call 的区别
apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组(方便记忆:call有两个l,表示可以传递多个参数)
bind 和 apply、call 区别
call、apply都是直接调用,bind生成的this指向改变函数需要手动调用
JavaScript深入之从原型到原型链
比较常见的几种:
js复制代码function Parent(name) {
this.name=name;
}
Parent.prototype.sayName=function() {
console.log('parent name:', this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name=name;
}
function create(proto) {
function F(){}
F.prototype=proto;
return new F();
}
Child.prototype=create(Parent.prototype);
Child.prototype.sayName=function() {
console.log('child name:', this.name);
}
Child.prototype.constructor=Child;
var parent=new Parent('father');
parent.sayName(); // parent name: father
var child=new Child('son', 'father');
其他几种继承方式,可参考:JavaScript常用八种继承方案
深拷贝: JSON.parse(JSON.stringify(data)) 递归
浅拷贝: Object.assign() 扩展运算符(...) Array.prototype.concat() Array.prototype.slice()
说说事件循环机制(满分答案来了)
防抖: 防抖就是将一段时间内连续的多次触发转化为一次触发。一般可以使用在用户输入停止一段时间过后再去获取数据,而不是每次输入都去获取
防抖应用场景:
节流: 节流,顾名思义,控制流量。用于用户在与页面交互时控制事件发生的频率,一般场景是单位的时间或其它间隔内定时执行操作。一段时间内,事件在每次到达我们规定的间隔 n 秒时触发一次
节流应用场景:
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
js复制代码function curry(fn, args) {
var length=fn.length;
var args=args || [];
return function(){
newArgs=args.concat(Array.prototype.slice.call(arguments));
if (newArgs.length < length) {
return curry.call(this,fn,newArgs);
} else {
return fn.apply(this,newArgs);
}
}
}
function multiFn(a, b, c) {
return a * b * c;
}
var multi=curry(multiFn);
multi(2)(3)(4);
multi(2,3,4);
multi(2)(3,4);
multi(2,3)(4);
这里面包含了大部分的常见手写代码: JavaScript手写代码无敌秘籍
注: const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
promise是异步编程的一种解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息
详细的可以参考:要就来45道Promise面试题一次爽到底
类定义
与函数类型相似,定义类也有两种主要方式:类声明和类表达式。这两种方式都使用 class 关键 字加大括号:
js复制代码class Person {} // 类声明
const Animal=class {}; // 类表达式
与函数表达式类似,类表达式在它们被求值前也不能引用。不过,与函数定义不同的是,虽然函数 声明可以提升,但类定义不能:
js复制代码console.log(FunctionExpression); // undefined
var FunctionExpression=function() {};
console.log(FunctionExpression); // function() {}
console.log(FunctionDeclaration); // FunctionDeclaration() {}
function FunctionDeclaration() {}
console.log(FunctionDeclaration); // FunctionDeclaration() {}
console.log(ClassExpression); // undefined
var ClassExpression=class {};
console.log(ClassExpression); // class {}
console.log(ClassDeclaration); // ReferenceError: ClassDeclaration is not defined
class ClassDeclaration {}
console.log(ClassDeclaration); // class ClassDeclaration {}
类构成
类可以包含构造函数方法、实例方法、获取函数、设置函数和静态类方法,但这些都不是必需的。 空的类定义照样有效。默认情况下,类定义中的代码都在严格模式下执行
构造函数 constructor
constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。
类的实例化
class 的实例化必须通过 new 关键字
js复制代码class Example {}
let exam1=Example();
// Class constructor Example cannot be invoked without 'new'
使用 new 调用类的构造函数会执行如下操作。
(1) 在内存中创建一个新对象。
(2) 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。
(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
(4) 执行构造函数内部的代码(给新对象添加属性)。
(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
类的所有实例共享一个原型对象
js复制代码class Example {
constructor(a, b) {
this.a=a;
this.b=b;
console.log('Example');
}
sum() {
return this.a + this.b;
}
}
let exam1=new Example(2, 1);
let exam2=new Example(3, 1);
console.log(exam1._proto_==exam2._proto_); // true
exam1._proto_.sub=function () {
return this.a - this.b;
}
console.log(exam1.sub()); // 1
console.log(exam2.sub()); // 2
上面代码中,exam1和exam2都是Example的实例,它们的原型都是Example.prototype,所以__proto__属性是相等的
setter、getter
在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
静态方法 static
类(class)通过 static 关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。这些通常是实用程序方法,例如创建或克隆对象的功能。
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
js复制代码class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo=new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
关键字 super
super关键字用于访问和调用一个对象的父对象上的函数。
继承 extends
ES6 类支持单继承。使用 extends 关键字,就可以继承任何拥有[[Construct]]和原型的对象。 很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数(保持向后兼容):
js复制代码class Vehicle {}
// 继承类
class Bus extends Vehicle {}
let b=new Bus();
console.log(b instanceof Bus); // true
console.log(b instanceof Vehicle); // true
function Person() {}
// 继承普通构造函数
class Engineer extends Person {}
let e=new Engineer();
console.log(e instanceof Engineer); // true
console.log(e instanceof Person); // true
大概步骤如下,具体要针对具体业务封装:
js复制代码// 创建 XMLHttpRequest 对象
var ajax=new XMLHttpRequest();
// 规定请求的类型、URL 以及是否异步处理请求。
ajax.open('GET', url);
// 发送信息至服务器时内容编码类型
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 发送请求
ajax.send(null);
// 接受服务器响应数据
ajax.onreadystatechange=function () {
if (obj.readyState==4 && (obj.status==200 || obj.status==304)) {
}
};
状态码 | 含义 |
200 | 表示从客户端发来的请求在服务器端被正常处理了 |
204 | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
301 | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
304 | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。 |
400 | 表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求 |
401 | 表示未授权(Unauthorized),当前请求需要用户验证 |
403 | 表示对请求资源的访问被服务器拒绝了 |
404 | 表示服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用 |
500 | 表示服务器端在执行请求时发生了错误。也有可能是Web应用存在的bug或某些临时的故障 |
502 | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
503 | 表示服务器暂时处于超负载或正在进行停机维护,现在无法处理请求 |
504 | 网关超时, 服务器作为网关或代理,但是没有及时从上游服务器收到请求 |
Request header | 解释 |
Accept | 指定客户端能够接收的内容类型,如:application/json, text/plain |
Accept-Encoding | 指定浏览器可以支持的web服务器返回内容压缩编码类型,如:gzip, deflate, br |
Accept-Language | 浏览器所希望的语言种类 |
Cache-Control | 缓存机制,默认no-cache |
Connec-Length | 请求头的长度 |
Content-Type | 发送的数据类型, 如:application/x-www-form-urlencoded, |
Connection | 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器 |
Host | 指定请求的服务器的域名和端口号 |
If-Modified-Since | 只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答 |
Referer | 包含一个URL,用户从该URL代表的页面出发访问当前请求的页面 |
User-Agent | 浏览器信息,如果Servlet返回的内容与浏览器类型有关则该值非常有用 |
Cookie | 这是最重要的请求头信息之一 |
Response header | 解释 |
Allow | 服务器支持哪些请求方法(如GET、POST等) |
Content-Encoding | 文档的编码(Encode)方法。 |
Content-Length | 表示内容长度。 |
Content-Type | 表示后面的文档属于什么MIME类型。 |
Date | 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦 |
Expires | 应该在什么时候认为文档已经过期,从而不再缓存它? |
Last-Modified | 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期, |
Location | 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302 |
Refresh | 表示浏览器应该在多少时间之后刷新文档,以秒计 |
Server | 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置 |
Set-Cookie | 设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie |
WWW-Authenticate | 客户应该在Authorization头中提供什么类型的授权信息? |
跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。浏览器从一个域名的网页去请求另一个域名的资源时,出现域名、端口、协议任一不同,都属于跨域。
跨域解决方案:
详情见:九种跨域方式实现原理(完整版)
预请求就是复杂请求(可能对服务器数据产生副作用的HTTP请求方法,如put,delete都会对服务器数据进行更修改,所以要先询问服务器)。
跨域请求中,浏览器自发的发起的预请求,浏览器会查询到两次请求,第一次的请求参数是options,以检测试实际请求是否可以被浏览器接受
什么情况下发生
例如设置了post请求的content-type:application/json,就会发生预请求
详细可以参考: 从输入URL开始建立前端知识体系
三次握手
第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于 SYN_SEND 状态。
第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD 的状态。
第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接
四次挥手
第一次挥手:客户端先发送FIN报文(第24帧),用来关闭主动方到被动关闭方的数据传送,也就是客户端告诉服务器:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,客户端依然会重发这些数据),但此时客户端还可以接受数据。
第二次挥手:Server端接到FIN报文后,如果还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以服务器端先发送ACK(第25帧),告诉Client端:请求已经收到了,但是我还没准备好,请继续等待停止的消息。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。
第三次挥手:当Server端确定数据已发送完成,则向Client端发送FIN报文(第26帧),告诉Client端:服务器这边数据发完了,准备好关闭连接了。
第四次挥手:Client端收到FIN报文后,就知道可以关闭连接了,但是他还是不相信网络,所以发送ACK后进入TIME_WAIT状态(第27帧), Server端收到ACK后,就知道可以断开连接了。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,最后,Client端也可以关闭连接了至此,TCP连接就已经完全关闭了!
为了方便记忆,整理个白话文版本,以找工作和离职举例(客户端=小明,服务端=人事)
第一次握手:由小明发起,小明向招聘人事发送了一份简历,里面包含了小明的个人基本信息
第二次握手:由人事发起,人事收到小明的简历后,安排面试,面试通过后,发送了一份offer给小明
第三次握手:由小明发起,小明收到offer后,会发送一个确认offer的回复,表示已经收到offer
第一次挥手:由小明发起,告诉服务器我要离职跑路了
第二次挥手:由人事发起,告诉小明我知道你要离职了,但是你先把工作交接好
第三次挥手:由人事发起,我看你的交接流程都走完了,你可以走人了
第四次挥手:由小明发起,收到人事通知离职流程已经走完了,告诉人事我明白就不来了,人事收到消息把此人从公司注销
大概流程如下:
浏览器的本地存储主要分为Cookie、WebStorage和IndexedDB, 其中WebStorage又可以分为localStorage和sessionStorage。接下来我们就来一一分析这些本地存储方案。
Cookie
HTTP Cookie,通常叫做Cookie,一开始是在客户端用于存储会话信息的。
Cookie主要构成
Cookie的原理
第一次访问网站时,浏览器发出请求,服务器响应请求后,会在响应头中添加一个Set-Cookie,将cookie放入响应请求中。
在第二次发起请求时,浏览器通过Cookie请求头部将cookie信息送给服务器,服务端根据cookie信息辨别用户身份。
Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。
Cookie的生成
Cookie的生成方式主要有两种:
服务端设置方式参考上面Cookie的原理,具体的实现方式自行查阅相关资料。客户端设置Cookie方法如下:
js复制代码document.cookie="name=zhangsan; age=20"
Cookie的缺点
Web Storage
Web Storage分为localStorage和sessionStorage
localStorage
localStorage有以下几个特点:
使用方法:
js复制代码// 设置
localStorage.setItem('name', '张三')
localStorage.age='25'
// 取值
localStorage.getItem('name')
let age=localStorage.age
// 移除
localStorage.removeItem('name')
// 移除所有
localStorage.clear()
sessionStorage
sessionStorage对象存储特定于某个会话的数据,当这个会话的页签或浏览器关闭,sessionStorage也就消失了。
页面刷新之后,存储在sessionStorage中的数据仍然存在可用。
sessionStorage的特点:
使用方法:
js复制代码// 设置
sessionStorage.setItem('name', '张三')
sessionStorage.age='25'
// 取值
sessionStorage.getItem('name')
let age=sessionStorage.age
// 移除
sessionStorage.removeItem('name')
// 移除所有
sessionStorage.clear()
sessionStorage和localStorage的区别:localStorage的数据可以长期保留,sessionStorage的数据在关闭页面后即被清空
IndexedDB
IndexedDB,全称Indexed Database API,是浏览器中保持结构化数据的一种数据库。
IndexedDB的思想是创建一套API,方便保存和读取JavaScript对象,同时支持查询和搜索。
IndexedDB特点
IndexedDB的入门教程,可以查看阮一峰老师的文章:浏览器数据库 IndexedDB 入门教程
总结
介绍
浏览器的 Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。其原理是:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大并且GC时停止响应其他操作,所以垃圾回收器会按照固定的时间间隔周期性的执行。
不再使用的变量也就是生命周期结束的变量,当然只可能是局部变量,全局变量的生命周期直至浏览器卸载页面才会结束。局部变量只在函数的执行过程中存在,而在这个过程中会为局部变量在栈或堆上分配相应的空间,以存储它们的值,然后在函数中使用这些变量,直至函数结束,而闭包中由于内部函数的原因,外部函数并不能算是结束。
还是上代码说明吧:
js复制代码function fn1() {
var obj={ name: 'hanzichi', age: 10 };
}
function fn2() {
var obj={ name:'hanzichi', age: 10 };
return obj;
}
var a=fn1();
var b=fn2();
我们来看代码是如何执行的。首先定义了两个function,分别叫做fn1和fn2,当fn1被调用时,进入fn1的环境,会开辟一块内存存放对象{name: 'hanzichi', age: 10},而当调用结束后,出了fn1的环境,那么该块内存会被js引擎中的垃圾回收器自动释放;在fn2被调用的过程中,返回的对象被全局变量b所指向,所以该块内存并不会被释放。
这里问题就出现了:到底哪个变量是没有用的?所以垃圾收集器必须跟踪到底哪个变量没用,对于不再有用的变量打上标记,以备将来收回其内存。用于标记的无用变量的策略可能因实现而有所区别,通常情况下有两种实现方式:标记清除和引用计数。引用计数不太常用,标记清除较为常用。
标记清除
js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。
垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。 到目前为止,IE9+、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。
引用计数
引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为0的值所占用的内存。
js复制代码function test() {
var a={}; // a的引用次数为0
var b=a; // a的引用次数加1,为1
var c=a; // a的引用次数再加1,为2
var b={}; // a的引用次数减1,为1
}
Netscape Navigator3是最早使用引用计数策略的浏览器,但很快它就遇到一个严重的问题:循环引用。循环引用指的是对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。
js复制代码function fn() {
var a={};
var b={};
a.pro=b;
b.pro=a;
}
fn();
以上代码a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,但是在引用计数策略下,因为a和b的引用次数不为0,所以不会被垃圾回收器回收内存,如果fn函数被大量调用,就会造成内存泄露。在IE7与IE8上,内存直线上升。
我们知道,IE中有一部分对象并不是原生js对象。例如,其内存泄露DOM和BOM中的对象就是使用C++以COM对象的形式实现的,而COM对象的垃圾回收机制采用的就是引用计数策略。因此,即使IE的js引擎采用标记清除策略来实现,但js访问的COM对象依然是基于引用计数策略的。换句话说,只要在IE中涉及COM对象,就会存在循环引用的问题。
js复制代码var element=document.getElementById("some_element");
var myObject=new Object();
myObject.e=element;
element.o=myObject;
这个例子在一个DOM元素(element)与一个原生js对象(myObject)之间创建了循环引用。其中,变量myObject有一个属性e指向element对象;而变量element也有一个属性o回指myObject。由于存在这个循环引用,即使例子中的DOM从页面中移除,它也永远不会被回收。
举个栗子:
js复制代码myObject.element=null;
element.o=null;
window.onload=function outerFunction() {
var obj=document.getElementById("element");
obj.onclick=function innerFunction(){};
obj=null;
};
这段代码看起来没什么问题,但是obj引用了document.getElementById('element'),而document.getElementById('element')的onclick方法会引用外部环境中的变量,自然也包括obj,是不是很隐蔽啊。(在比较新的浏览器中在移除Node的时候已经会移除其上的event了,但是在老的浏览器,特别是ie上会有这个bug)
解决办法:
最简单的方式就是自己手工解除循环引用,比如刚才的函数可以这样
js复制代码myObject.element=null;
element.o=null;
window.onload=function outerFunction(){
var obj=document.getElementById("element");
obj.onclick=function innerFunction(){};
obj=null;
};
将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾回收器下次运行时,就会删除这些值并回收它们占用的内存。
要注意的是,IE9+并不存在循环引用导致Dom内存泄露问题,可能是微软做了优化,或者Dom的回收方式已经改变
在讨论回流与重绘之前,我们要知道:
一句话:回流必将引起重绘,重绘不一定会引起回流
回流 (Reflow)
当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
会导致回流的操作:
一些常用且会导致回流的属性和方法:
重绘 (Repaint)
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
性能影响
回流比重绘的代价要更高。
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。
现代浏览器会对频繁的回流或重绘操作进行优化:
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当你访问以下属性或方法时,浏览器会立刻清空队列:
因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。
如何避免
CSS
JavaScript
通俗易懂,了解什么是DNS及查询过程
CDN是什么?使用CDN有什么优势?
最全的 Vue 面试题+详解答案
Vue.js 技术揭秘
高频前端面试题汇总之React篇(上)
高频前端面试题汇总之React篇(下)
搞懂这12个Hooks,保证让你玩转React
React 源码剖析系列 - 生命周期的管理艺术
React Hooks 原理
深入理解 React 高阶组件
前端性能优化手段从以下几个方面入手:加载优化、执行优化、渲染优化、样式优化、脚本优化
加载优化:减少HTTP请求、缓存资源、压缩代码、无阻塞、首屏加载、按需加载、预加载、压缩图像、减少Cookie、避免重定向、异步加载第三方资源
执行优化:CSS写在头部,JS写在尾部并异步、避免img、iframe等的src为空、尽量避免重置图像大小、图像尽量避免使用DataURL
渲染优化:设置viewport、减少DOM节点、优化动画、优化高频事件、GPU加速
样式优化:避免在HTML中书写style、避免CSS表达式、移除CSS空规则、正确使用display:display、不滥用float等
脚本优化:减少重绘和回流、缓存DOM选择与计算、缓存.length的值、尽量使用事件代理、尽量使用id选择器、touch事件优化
加载优化
执行优化
渲染优化
样式优化
脚本优化
Webpack面试题
当面试官问Webpack的时候他想知道什么
TypeScript免费视频图文教程(2W字)
算法这块呢,应该是很多人头疼的地方,没有其他方法,只能去LeetCode老老实实刷题
JavaScript 数据结构与算法之美
就是攻击者想尽一切办法将可以执行的代码注入到网页中, 主要分为以下几种
存储型(server端)
场景:见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等
攻击步骤:
反射型(Server端)
与存储型的区别在于,存储型的恶意代码存储在数据库中,反射型的恶意代码在URL上
场景:通过 URL 传递参数的功能,如网站搜索、跳转等
攻击步骤:
Dom 型(浏览器端)
DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞
场景:通过 URL 传递参数的功能,如网站搜索、跳转等
攻击步骤:
预防方案:
防止攻击者提交恶意代码,防止浏览器执行恶意代码
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
攻击流程举例
攻击类型
预防方案:
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。)
作者:前端老干部
链接:https://juejin.cn/post/7127217262133510158
、 介绍一下标准的CSS的盒子模型?与低版本IE的盒子模型有什么不同的?
标准盒子模型:宽度=内容的宽度(content)+ border + padding + margin
低版本IE盒子模型:宽度=内容宽度(content+border+padding)+ margin
2、 box-sizing属性?
用来控制元素的盒子模型的解析模式,默认为content-box
context-box:W3C的标准盒子模型,设置元素的 height/width 属性指的是content部分的高/宽
border-box:IE传统盒子模型。设置元素的height/width属性指的是border + padding + content部分的高/宽
3 、CSS选择器有哪些?哪些属性可以继承?
CSS选择符:id选择器(#myid)、类选择器(.myclassname)、标签选择器(div, h1, p)、相邻选择器(h1 + p)、子选择器(ul > li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel="external"])、伪类选择器(a:hover, li:nth-child)
可继承的属性:font-size, font-family, color
不可继承的样式:border, padding, margin, width, height
优先级(就近原则):!important > [ id > class > tag ]
!important 比内联优先级高
4、 CSS优先级算法如何计算?
元素选择符: 1
class选择符: 10
id选择符:100
元素标签:1000
5、 CSS3新增伪类有那些?
p:first-of-type 选择属于其父元素的首个元素
p:last-of-type 选择属于其父元素的最后元素
p:only-of-type 选择属于其父元素唯一的元素
p:only-child 选择属于其父元素的唯一子元素
p:nth-child(2) 选择属于其父元素的第二个子元素
:enabled :disabled 表单控件的禁用状态。
:checked 单选框或复选框被选中。
6 、如何居中div?如何居中一个浮动元素?如何让绝对定位的div居中?
div:
border: 1px solid red;margin: 0 auto; height: 50px;width: 80px;
浮动元素的上下左右居中:
border: 1px solid red;float: left; position: absolute;width: 200px; height: 100px;left: 50%;top: 50%; margin: -50px 0 0 -100px;
绝对定位的左右居中:
border: 1px solid black;position: absolute; width: 200px;height: 100px;margin: 0 auto; left: 0;right: 0;
还有更加优雅的居中方式就是用flexbox,我以后会做整理。
7、 display有哪些值?说明他们的作用?
inline(默认)--内联
none--隐藏
block--块显示
table--表格显示
list-item--项目列表
inline-block
8、 position的值?
static(默认):按照正常文档流进行排列;
relative(相对定位):不脱离文档流,参考自身静态位置通过 top, bottom, left, right 定位;
absolute(绝对定位):参考距其最近一个不为static的父级元素通过top, bottom, left, right 定位;
fixed(固定定位):所固定的参照对像是可视窗口。
9、 CSS3有哪些新特性?
10、 请解释一下CSS3的flexbox(弹性盒布局模型),以及适用场景?
该布局模型的目的是提供一种更加高效的方式来对容器中的条目进行布局、对齐和分配空间。在传统的布局方式中,block 布局是把块在垂直方向从上到下依次排列的;而 inline 布局则是在水平方向来排列。弹性盒布局并没有这样内在的方向限制,可以由开发人员自由操作。
试用场景:弹性布局适合于移动前端开发,在Android和ios上也完美支持。
11、 用纯CSS创建一个三角形的原理是什么?
首先,需要把元素的宽度、高度设为0。然后设置边框样式。
width: 0;height: 0;border-top: 40px solid transparent; border-left: 40px solid transparent;border-right: 40px solid transparent; border-bottom: 40px solid #ff0000;
12、 一个满屏品字布局如何设计?
第一种真正的品字:
第二种全屏的品字布局:
上面的div设置成100%,下面的div分别宽50%,然后使用float或者inline使其不换行。
13 、常见的兼容性问题?
{background-color:#f1ee18;/*所有识别*/.background-color:#00deff; /*IE6、7、8识别*/+background-color:#a200ff;/*IE6、7识别*/_background-color:#1e0bd1;/*IE6识别*/}
14、 为什么要初始化CSS样式
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
15、 absolute的containing block计算方式跟正常流有什么不同?
无论属于哪种,都要先找到其祖先元素中最近的 position 值不为 static 的元素,然后再判断:
如果都找不到,则为 initial containing block。
补充:
16、CSS里的visibility属性有个collapse属性值?在不同浏览器下以后什么区别?
当一个元素的visibility属性被设置成collapse值后,对于一般的元素,它的表现跟hidden是一样的。
17、 display:none与visibility:hidden的区别?
display:none 不显示对应的元素,在文档布局中不再分配空间(回流+重绘)
visibility:hidden 隐藏对应元素,在文档布局中仍保留原来的空间(重绘)
18、 position跟display、overflow、float这些特性相互叠加后会怎么样?
display属性规定元素应该生成的框的类型;position属性规定元素的定位类型;float属性是一种布局方式,定义元素在哪个方向浮动。
类似于优先级机制:position:absolute/fixed优先级最高,有他们在时,float不起作用,display值需要调整。float 或者absolute定位的元素,只能是块元素或表格。
19 、对BFC规范(块级格式化上下文:block formatting context)的理解?
BFC规定了内部的Block Box如何布局。
定位方案:
满足下列条件之一就可触发BFC
20、 为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?
浮动元素碰到包含它的边框或者浮动元素的边框停留。由于浮动元素不在文档流中,所以文档流的块框表现得就像浮动框不存在一样。浮动元素会漂浮在文档流的块框上。
浮动带来的问题:
清除浮动的方式:
21、 上下margin重合的问题
在重合元素外包裹一层容器,并触发该容器生成一个BFC。
例子:
<div class="aside"></div> <div class="text"> <div class="main"></div> </div> <!--下面是css代码--> .aside { margin-bottom: 100px; width: 100px; height: 150px; background: #f66; } .main { margin-top: 100px; height: 200px; background: #fcc; } .text{ /*盒子main的外面包一个div, 通过改变此div的属性使两个盒子分属于两个不同的BFC, 以此来阻止margin重叠*/ overflow: hidden; //此时已经触发了BFC属性。 }
22、设置元素浮动后,该元素的display值是多少?
自动变成display:block
23、 移动端的布局用过媒体查询吗?
通过媒体查询可以为不同大小和尺寸的媒体定义不同的css,适应相应的设备的显示。
24 、使用 CSS 预处理器吗?
Less sass
25、 CSS优化、提高性能的方法有哪些?
26、 浏览器是怎样解析CSS选择器的?
CSS选择器的解析是从右向左解析的。若从左向右的匹配,发现不符合规则,需要进行回溯,会损失很多性能。若从右向左匹配,先找到所有的最右节点,对于每一个节点,向上寻找其父节点直到找到根元素或满足条件的匹配规则,则结束这个分支的遍历。
两种匹配规则的性能差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点),而从左向右的匹配规则的性能都浪费在了失败的查找上面。
而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 Render Tree。
27 、在网页中的应该使用奇数还是偶数的字体?为什么呢?
使用偶数字体。偶数字号相对更容易和 web 设计的其他部分构成比例关系。Windows 自带的点阵宋体(中易宋体)从 Vista 开始只提供 12、14、16 px 这三个大小的点阵,而 13、15、17 px时用的是小一号的点。(即每个字占的空间大了 1 px,但点阵没变),于是略显稀疏。
28、 margin和padding分别适合什么场景使用?
何时使用margin:
何时使用padding:
兼容性的问题:在IE5 IE6中,为float的盒子指定margin时,左侧的margin可能会变成两倍的宽度。通过改变padding或者指定盒子的display:inline解决。
29 、元素竖向的百分比设定是相对于容器的高度吗?
当按百分比设定一个元素的宽度时,它是相对于父容器的宽度计算的,但是,对于一些表示竖向距离的属性,例如 padding-top , padding-bottom , margin-top , margin-bottom 等,当按百分比设定它们时,依据的也是父容器的宽度,而不是高度。
30 、全屏滚动的原理是什么?用到了CSS的哪些属性?
31、 什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的IE?
响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。
基本原理是通过媒体查询检测不同的设备屏幕尺寸做处理。
页面头部必须有meta声明的viewport。
<meta name=’viewport’ content=”width=device-width, initial-scale=1. maximum-scale=1,user-scalable=no”>
32、 视差滚动效果?
视差滚动(Parallax Scrolling)通过在网页向下滚动的时候,控制背景的移动速度比前景的移动速度慢来创建出令人惊叹的3D效果。
33、 ::before 和 :after中双冒号和单冒号有什么区别?解释一下这2个伪元素的作用
:before 和 :after 这两个伪元素,是在CSS2.1里新出现的。起初,伪元素的前缀使用的是单冒号语法,但随着Web的进化,在CSS3的规范里,伪元素的语法被修改成使用双冒号,成为::before ::after
34、 你对line-height是如何理解的?
行高是指一行文字的高度,具体说是两行文字间基线的距离。CSS中起高度作用的是height和line-height,没有定义height属性,最终其表现作用一定是line-height。
单行文本垂直居中:把line-height值设置为height一样大小的值可以实现单行文字的垂直居中,其实也可以把height删除。
多行文本垂直居中:需要设置display属性为inline-block。
35 、怎么让Chrome支持小于12px 的文字?
p{font-size:10px;-webkit-transform:scale(0.8);} //0.8是缩放比例
36、 让页面里的字体变清晰,变细用CSS怎么做?
-webkit-font-smoothing在window系统下没有起作用,但是在IOS设备上起作用-webkit-font-smoothing:antialiased是最佳的,灰度平滑。
37、 position:fixed;在android下无效怎么处理?
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
38、 如果需要手动写动画,你认为最小时间间隔是多久,为什么?
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms。
39、 li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
行框的排列会受到中间空白(回车空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔,把字符大小设为0,就没有空格了。
解决方法:
40、 display:inline-block 什么时候会显示间隙?
41、 有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度
外层div使用position:relative;高度要求自适应的div使用position: absolute; top: 100px; bottom: 0; left: 0
42、 png、jpg、gif 这些图片格式解释一下,分别什么时候用。有没有了解过webp?
43、 style标签写在body后与body前有什么区别?
页面加载自上而下 当然是先加载样式。
写在body标签后由于浏览器以逐行方式对HTML文档进行解析,当解析到写在尾部的样式表(外联或写在style标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染,在windows的IE下可能会出现FOUC现象(即样式失效导致的页面闪烁问题)
44、 CSS属性overflow属性定义溢出元素内容区的内容会如何处理?
参数是scroll时候,必会出现滚动条。
参数是auto时候,子元素内容大于父元素时出现滚动条。
参数是visible时候,溢出的内容出现在父元素之外。
参数是hidden时候,溢出隐藏。
45、 阐述一下CSS Sprites
将一个页面涉及到的所有图片都包含到一张大图中去,然后利用CSS的 background-image,background- repeat,background-position 的组合进行背景定位。利用CSS Sprites能很好地减少网页的http请求,从而大大的提高页面的性能;CSS Sprites能减少图片的字节。
关注此头条号“互联网IT信息”——>私信发送 “天猫css” ,(注意:css全是小写)即可得到源代码的获取方式。
案例和由此案例重点讲解的知识点介绍
案例代码实现
css三大特性知识点详解
此案例是页面,效果如下:
此页面的技术实现解析:
使用标签选择器定义通用样式,通过css层叠性和继承性来让通用标签的样式被继承到类选择器上
此案例中主要用到了,基于此,我们会系统的将如下知识点全部讲解:
css三大特性:层叠性、继承性、优先级
第一步:使用块级标签和无序列表编写导航侧边栏的html
第二步:通过标签选择器定义ul li a的通用样式
第三步:定义外层div样式
第四步:通过类选择器定义无序列表样式,其中li和a标签的基本样式继承自第二步的标签选择器
CSS三大特性:
层叠性、继承性、优先级
1)层叠性:
1. 给一个标签设置的样式发生冲突的时候即样式的覆盖
2. 浏览器的渲染机制是从上到下的,当有冲突的时候就采用最后的那个样式
例如:
h2.grape {color: purple;}
h2 {color: siver;}
层叠性代码实例:
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>Document</title>
<styletype="text/css">
.two{
color: green;
}
.one{
color: red;
font-size: 30px;
}
.tree{
color: yellow;
font-size: 40px;
}
</style>
</head>
<body>
<pclass="one two tree">
一段文字
</p>
</body>
</html>
2)继承性:继承就是子标签继承了上级标签的CSS样式的属性
1,发生的前提是:标签之间属于一种嵌套关系
2,文字颜色可以之间继承
3,字体大小可以继承
4,字体可以继承
5,行高也可以实现继承
6, 与文字有关的属性都可以,实现继承
特殊注意:
a标签超链接不能实现字体颜色的继承,字体大小可以继承
h1不可以继承文字的大小,继承过来还会做一个计算
继承性代码实例:
<!DOCTYPEhtml>
<html>
<head>
<metacharset="UTF-8">
<title></title>
<style>
div{
color: red;
font-size: 30px;
}
</style>
</head>
<body>
<div>
<ahref="">a</a>
</div>
</body>
</html>
3) 优先级
具体解释如下:
内联样式最大,内联样式的优先级最高。
ID选择器的优先级,仅次于内联样式。
类选择器优先级低于ID选择器
标签选择器低于类选择器。
补充:
权重相同时,CSS遵循就近原则。也就是说靠近元素的样式具有最大的优先级,或者说排在最后的样式优先级最大。
所有都相同时,声明靠后的优先级大。
CSS定义了一个!important命令,该命令被赋予最大的优先级。也就是说不管权重如何以及样式位置的远近,!important都具有最大优先级。
综述:
-行内样式 > 页内样式 > 外部引用样式 > 浏览器默认样式
important > 内联 > ID > 伪类|类 | 属性选择 > 标签 > 伪对象 > 通配符 > 继承
css优先级代码实例:
<!DOCTYPE>
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/>
<title>无标题文档</title>
<style>
*{ font-size:56px;}
p{ font-size:32px; color:#60C;}
.d{ color:#F0F;}
#hei{ color:#96F;}
</style>
</head>
<body>
<h1>我是标题</h1>
<p>我是段落</p>
<p>我是段落2</p>
<pclass="d"id="hei"style="color:#FF0;">我是段落3</p>
<ahref="#">我是超链接</a>
<span>我是备胎标签</span>
</body>
</html>
*请认真填写需求信息,我们会在24小时内与您取得联系。