interview
HTML&CSS
浏览器标准模式和怪异模式之间的区别
标准模式 | 怪异模式 | |
---|---|---|
盒模型 | 标准盒子模型(实际宽度为设置的width+padding+border+margin) | IE盒模型(实际宽度为设置的width+margin) |
图片元素的垂直对齐方式 | inline元素和table-cell元素,vertical-align的默认取值为baseline | table单元格中的的图片的vertical-align属性为bottom,因此图片底部有几像素的空间 |
<table>元素中的字体 | font的属性都是可以继承的 | 对于table元素,字体的某些属性是不会从body等封装元素中得到继承,特别是font-size |
元素百分比高度 | 高度取决于内容变化 | 百分比高度都正确使用 |
行内元素/块级元素/空元素
行内元素
- span
- a
- img
- b/strong
- i/em
- small/big
- input
- select
块级元素
- div
- p
- table
- ul/ol/li
- h1-h6
空元素
- br
- hr
- img
- input
- link
- meta
介绍一下你对浏览器内核的理解
浏览器主要分为两个部分:渲染引擎和JS引擎
渲染引擎主要负责渲染静态页面
JS引擎主要负责解析和执行JS实现页面的动态效果
Flex布局
flex其实是flexible box的缩写,也就是弹性布局,这种布局给盒子模型提供了很大的灵活性.容器的主要属性有flex-direction,用来设置主轴的排列方向,flex-wrap用来设置换行.justify-content用来设置主轴的对齐方式,align-items用来设置纵轴的对齐方式,项目主要用到的属性就是flex.通过将自适应高度的盒子设置为flex:1
实现一个左侧宽度固定,右侧自适应的布局
- 利用左侧浮动元素脱离文档流,右侧元素会直接向父级元素左侧靠拢,然后再设置左侧的边距把内容推出来
- 父元素利用弹性布局,子元素中将左侧设置为固定宽度,右侧flex属性设置为1
- 利用BFC,因为BFC不能与浮动元素重叠,可以将左侧元素设置为左浮动,然后通过overflow:hidden让右侧盒子形成一个BFC.
实现一个两侧宽度固定,中间自适应布局
-
弹性布局,左右固定宽度,中间flex:1
-
浮动,左右元素浮动为固定宽度,中间元素放到最后
-
利用左右两侧都固定定位,中间设置左右margin为左右的width
水平垂直居中
垂直改变top或者bottom的值
水平改变left或者right的值
.box1{
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
}
这种方式只是适用于已知盒子大小的情况
.box2{
width: 200px;
height: 200px;
background-color: blue;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
是用绝对定位和margin:auto.
.box3{
width: 300px;
height: 300px;
background-color: green;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
利用绝对定位和transform
弹性布局,弹性布局有两种实现方式
给父盒子设置display:flex;和align-items:center
还有一种就是给父盒子设置display:flex;flex-direction:colunm;justify-content:center;
清除浮动
浮动产生的原因:子元素脱离了文档流,父元素没有了高度.
清除浮动主要有三种方法
1.在浮动元素的后面使用一个空元素
,给他们设置clear:both;属性即可清除浮动
2.给浮动元素的父元素添加overflow:hidden属性
3.使用伪元素:after.给浮动元素的父元素添加一个clearfix的类名,然后给这个类名添加一个伪元素:after设置一下属性{content:‘’;height:0;display:block;clear:both;}
BFC
什么是BFC
BFC其实就是一个容器,然后容器的内部元素不能影响外部元素,反之也成立
BFC的布局规则
- 所有的块级元素在垂直方向上从左排列,左边距紧挨着父元素,独占一行
- 同一个BFC两个相邻的块级元素设置同一方向的margin会发生margin塌陷
- BFC的区域不会与浮动元素重合
- 计算BFC的高度时,浮动元素也参与计算
- BFC内部的子元素不能影响到外部元素,反之也成立
如何创建一个BFC
- Float的值不为none
- position的值不为static和relative
- display的值是inline-block,flex,inline-flex,table-caption,table-cell
- overflow的值不是Visible
BFC的作用
-
利用margin可以避免margin塌陷
- 让其中的一个元素形成一个独立的BFC
- 在一个元素身上设置足够的margin
-
清除浮动
overflow:hidden
什么是FOUC,如何避免
FOUC就是无样式内容闪烁,是因为在IE中通过@import导入css文件引起的
因为通过@import导入的css样式是在整个HTML文档DOM加载完毕之后才会开始加载css样式,我们可以将引入css的方法改成通过link引入就好了,因为通过link标签引入css样式是和HTML文档DOM一起加载
页面导入样式,link和@import的区别
- link属于XHTML标签,@import完全是CSS提供的一种方式.link标签除了可以加载CSS以外,还可以定义RSS,定义rel连接属性等,@import只能加载CSS
- 加载顺序的区别;当一个页面在加载的时候.link引入的CSS会同时和页面一起加载,@import引入的CSS文件要等页面加载完之后再加载.所以有时候浏览@import加载CSS的页面时会没有样式(就是闪烁),特别是网速比较慢的时候
- 兼容性的差别;@import是CSS2之后提出的,只支持IE5以上的浏览器.link没有兼容性问题
- 使用Javascript控制DOM改变样式时,只能使用link标签,因为通过@import不是DOM能够控制的
动画
GET和POST的区别
GET | POST | |
---|---|---|
浏览器回退 | 无害 | 再次提交请求 |
编码方式 | 只支持url编码 | 支持多种编码格式 |
参数长度 | 有长度限制 | 无长度限制 |
参数是否保留在历史记录 | 参完整的保留在浏览器历史记录 | 不会保留在浏览器历史记录 |
参数传递方式 | 通过url传递 | 放在Request Body请求体中 |
参数数据类型 | 只接受ASCII字符 | 没有限制 |
安全性 | 比POST更不安全(参数直接暴露在url) | 不安全 |
是否被浏览器主动cache | 会 | 不会,除非手动设置 |
产生TCP数据包的个数 | 一个 | 两个 |
1.GET在浏览器回退时是无害的,而POST会再次提交请求
2.GET请求会被浏览器主动cache,而POST不会,除非手动设置
3.GET请求只能进行url编码,而POST支持多种编码方式
4.GET请求参数会被完整保留在浏览器历史记录里,而POST的参数不会保留
5.GET请求在URL中传送的参数有长度限制,而POST没有
6.GET比POST更不安全,因为参数直接暴露在URl上,不能用来传递敏感信息.
7.GET参数通过URl传递,POST参数放在Request body中
8.对于参数的数据类型,GET只接受ASCII字符,而POST没有限制
9.GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
10.GET产生一个TCP数据包;POST产生两个TCP数据包
H5新特性
- 新增了语义化标签;header,main,footer,nav,section,article
- 增强型表单
- 双向通信webSocket
- 视频,音频 audio video 标签
- 图形 canvas,svg矢量图
- 提高性能充分利用电脑的CPU webWorks
- 本地存储;localstorage,sessionstorage
- 媒体查询(移动端适配)
- CSS3的美化
- 地理定位
CSS3新特性
-
选择器
添加了一些结构伪类选择器;first-of-type,last-of-type
-
背景和边框
边框border-radius,box-shadow
背景background-clip
-
文本效果
word-wrap 允许对单词进行拆分
-
2D/3D的转换
-
动画、过渡
transition,transform,animation
transform:scale,translate,rotate
-
多列布局
-
用户界面
box-sizing
如果需要手写动画,最小时间间隔是多少
大部分的显示器默认的60Hz,就是一秒刷新60次,1000/60=16.7ms
fixed和absolute的共同点
- 两者的display属性值都是block
- 都会脱离文档流
浏览器的最小字体是12px,如果还想要小,该怎么做?
- 通过设置元素的transfor:scale()属性
怎么实现0.5px的线
- 通过transform的scale缩放
- 使用linear-gradient(0deg,#fff,#000)
- 移动端可以通过通过初始缩放比例
- 通过box-shadow模糊距离为0.5px
媒体查询
概念
媒体查询就是根据不同的设备设定不同的CSS样式,使页面在不同的终端设备下达到不同的渲染效果
媒体查询使用方法
@media 媒体类型 and 媒体特性{自己设置的样式}
比如说 @media screen and max-width:600px
处理PC端浏览器兼容问题
-
是用normalize.css或者自己的reset.css解决不同浏览器的默认样式
-
引入html5shiv.js解决ie9以下浏览器对H5新增标签不识别的问题
-
引入respond.js解决ie9以下浏览器不支持媒体查询的问题
-
picturefill.js解决ie9,10,11等浏览器不支持pictrue标签的问题
-
添加私有前缀
-
求窗口大小的兼容写法
// 浏览器窗口可视区域大小(不包括工具栏和滚动条等边线)// 1600 * 525 var client_w = document.documentElement.clientWidth || document.body.clientWidth; var client_h = document.documentElement.clientHeight || document.body.clientHeight; // 网页内容实际宽高(包括工具栏和滚动条等边线)// 1600 * 8 var scroll_w = document.documentElement.scrollWidth || document.body.scrollWidth; var scroll_h = document.documentElement.scrollHeight || document.body.scrollHeight; // 网页内容实际宽高 (不包括工具栏和滚动条等边线)// 1600 * 8 var offset_w = document.documentElement.offsetWidth || document.body.offsetWidth; var offset_h = document.documentElement.offsetHeight || document.body.offsetHeight; // 滚动的高度 var scroll_Top = document.documentElement.scrollTop||document.body.scrollTop;
移动端适配问题
-
媒体查询
通过查询设备的宽度执行不同的css代码
优点
- 可以做到设备像素比的判断,方法简单,成本低,特别是对移动端和PC端维护同一套代码的时候.像Bootstrap等框架就是使用这种布局方式
- 图片便于修改,只需修改css文件
- 调整屏幕宽度的时候不用刷新页面即可响应式展示
缺点
- 代码量大,维护不方便
- 为了兼顾大屏幕或高清设置,会造成其他设备资源浪费,特别是加载图片资源
- 为了兼顾移动和PC端各自响应式的展示效果,会损失各自特有的交互方式
-
Flex弹性布局
-
rem+viewport缩放
根据屏幕宽度设定rem值,需要适配的元素都是用rem为单位,不需要适配的元素是用px为单位
rem和em的区别
rem是相对于HTML根元素的相对大小单位,通过它既可以做到只修改根元素就可以成比例的调整所有是用rem设置大小的元素
em是相对于父元素的相对大小单位
原理
根据rem将页面放大dpr倍,然后将viewport设置为1/dpr
-
是用vw和vh
这个vw和vh都是相当于把视口分成了100份
移动端兼容问题
-
移动端click事件有300ms延迟,往往会造成点击延迟甚至是失效,这是由于区分单击事件和双击缩放屏幕的历史原因造成的
解决方式
- fastclick路由解决手机端点击300ms延迟的问题
- zepto的touch模块,tap事件也是为了解决在click上的延迟问题
- 触摸屏的相应顺序为touchstart–>touchmove–>touchend–>click,也可以通过绑定ontouchstart事件,加快事件的响应,解决300ms的问题
-
一些情况下对非可点击元素(label,span)监听click事件,iso下不会触发,css添加cursor:pointer就行了.
-
禁止IOS识别长串数字为电话
<meta content= "telephone=no" name="format-detection">
解决移动端1px边框问题
因为css中1px并不等于移动设备的1px,这是因为不同的手机有不同的像素密度.在window对象中有一个devicePixelRatio属性,它可以反映css中的像素与设备的像素比.
devicePixelRatio的定义为:设备物理像素和设备独立像素的比例
-
使用0.5px边框;通过javascript检测浏览器能否处理0.5px的边框,如果可以的话就给html标签元素加个border-width:0.5px.
缺点
无法兼容安卓设备和IOS8以下设备
-
使用borde-image实现
-
对viewport+rem实现
在devicePixelRatio=2时,输出viewport:
<meta name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalabel=no">
当devicePixelRatio=3时,输出viewport
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
优点
- 所有场景都能满足
- 一套代码基本可以兼容所有布局
缺点
老项目修改代码过大,只适用于新项目
-
伪元素+transform实现
把之前元素的border去掉,利用伪元素重做设置border,并使用transform的scale将border缩小一半
实现一个正方面始终居中,正方面的大小自适应
* {
margin: 0;
padding: 0;
}
.father {
width: 50vh;
height: 50vh;
background: skyblue;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
}
px,rem,em的区别
px:相对于显示器屏幕分辨率长度单位
rem:是CSS3新增的一个相对单位,是相对于HMTL根元素大小的相对单位
em:相对于当前对象内文本的字体尺寸的相对单位
px与rem的选择
对于只需要适配少部分手机设备,且分辨率对页面影响不大的,使用px即可 。
对于需要适配各种移动设备,使用rem,例如只需要适配iPhone和iPad等分辨率差别比较挺大的设备。
Stylus,Less,Scss的区别
stylus | less | sass | |
---|---|---|---|
基本语法 | 没有花括号和分号 | 有花括号和分号 | 有花括号和分号 |
嵌套语法 | 没有花括号和分号 | 有花括号和分号 | 有花括号和分号 |
变量 | 对变量没有任何设定,但是不能以@开头 | 变量以@开头 | 变量以$开头 |
实现多行文本居中超出显示省略号
display: -webkit-box;
/-webkit-line-clamp: 3;
/-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
JavaScript
JS执行机制
首先,javascript是一门单线程的语言.javascript代码从上到下执行,有同步和异步代码,代码执行的过程中,同步任务和异步任务会进入到不同的"场所",同步任务进入主线程,异步任务进入到一个事件队列当中,当所有的同步任务都执行完了,就会去读取事件队列里面的函数,进入主线程执行,重复上述的过程就是常说的Event Loop.虽然在最新的HTML-5中提出了Web-Worker,但是javascript是单线程这一核心仍未改变.
Web-Worker
Web-Worker的作用,就是为Javascript创造多线程的环境,允许主线程创建Worker线程,将一些任务分配给Worker运行.在主线程运行的同时,Worker在后台运行,两者互不干扰,等到Worker线程完成计算任务,再把结果返回给主线程.这样的好处就是可以将一些计算比较密集或者高延迟的任务交给Worker线程负担,主线程就会很流畅,不会被阻塞.
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web-Worker使用注意点:
- 同源限制
- DOM限制
- 通信联系
- 脚本限制
JS数据类型
基本数据类型
- 字符串String
- 数字Number
- 布尔值Boolean
- Undefined
- Null
- Symbol
引用数据类型
- 对象Object
- 函数Function
- 时间Date
- 正则RegExp
- Error
- Math
- Arguments
- 数组Array
- 对象Object
JS内置对象
基本对象
- 函数Function
- 时间Date
- 正则RegExp
- 错误Error
- 默认参数Arguments
- Math
数据对象
基本类型
- 数字Number
- 字符串String
- 布尔Boolean
数据结构
- 数组Array
- 对象Object
JS实现异步编程的方法
优点 | 缺点 | |
---|---|---|
回调函数 | 简单,容易理解 | 不利于维护,代码耦合度搞高 |
事件监听 | 容易理解,可以绑定多个事件,每个事件可以指定多个回调函数 | 事件驱动,流程不清晰 |
发布/订阅(观察模式) | 类似于事件监听,但是可以通过消息中心,了解现在有多少发布者和订阅者 | |
Promise对象 | 可以利用.then方法,进行链式书写,书写成功和失败后的回调函数 | 编写和理解相对比较难 |
async函数 | 内置执行器、更好的语义、更广的适用性、返回的是Promise、结构清晰。 | 错误处理机制 |
JS延迟加载的方法
JS延迟加载就是等页面加载完成之后再加载JS文件,JS延迟加载有助于提高页面加载速度
1.defer
在script标签设置defer的属性值为defer,等于告诉浏览器,脚本立即下载,但是延迟执行
只适用于外部脚本文件
2.async属性
在script标签设置async属性.目的是不让页面等待脚本下载和执行,从而页面加载页面其他内容
只适用于外部脚本文件,不能控制加载的顺序
3.动态创建DOM
4.使用setTimeout延迟方法的加载时间
5.让JS最后加载
栈和堆的区别
栈 | 堆 | |
---|---|---|
存放内容 | 变量,基本数据类型和引用数据类型的地址 | 引用数据类型 |
储存特点 | 体积小,数据经常发生变化 | 体积大,数据不会经常变化 |
Event Loop
在javascript中,任务被分为两种,一种是宏任务(MacroTask)也叫Task,一种是微任务(MicroTask)
宏任务
scrip全部代码,setTimeout,setInterval,setImmediate,I/O,ULRendering
微任务
process.nextTick(Node独有),Promise,Object.observer(废弃),MutationObserver
浏览器中的Event Loop
javascript中有一个主线程和调用栈,所有的任务都在调用栈中等待主线程执行
ES6新特性
- 变量声明方式:let和const
- Promise
- 增强的对象字面量
- 箭头函数
- class类
- 字符串模板
- 解构
- 模块
- for…of循环
- Map,Set
面向对象和面向过程编程,他们之间的优缺点和异同
区别
面向过程
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步的实现,然后使用的时候一个一个一次调用就可以了
面向对象
面向对象就是把构成问题事务分解成各个对象,比如说这个对象负责这类功能,那个对象负责其他类功能,每一个对象完成的功能所整合起来完成整个问题的编程方式就是面向对象编程
面向对象的特点
封装性
函数的封装
对象的封装
模块的封装
继承性
原型链的继承
类的继承
组合寄生式继承
多态性
JS函数对类型没有要求,不同函数得到不同的结果,导致多态.其实严格来说的话,JS面向对象不存在多态,或者很难实现多态
各自的优缺点
面向对象 | 面向过程 | |
---|---|---|
优点 | 易维护,易复用,易扩展,耦合度低 | 性能比面向对象高 |
缺点 | 因为类调用时需要实例化,性能比面向过程低 | 不易维护,不易复用,不易扩展 |
继承
继承就是子类可以继承父类身上所有的属性和方法,子类也可以在自己身上自定义属性和方法.ECMAscript的继承主要是通过原型链的方式实现的.
继承的六种方法
-
原型链的继承
-
借用构造函数继承
-
组合继承(综合原型链和借用构造函数)
基本思路就是使用原型链继承原型上的属性和方法,通过借用构造函数继承实例属性
-
原型式继承
-
寄生式继承
-
寄生组合式继承(ES5最理想的状态)
//父类构造函数 function Person(name,sex,age){ this.name=name, this.sex=sex, this.skil=['吃饭','睡觉',] } //父类方法 Person.prototype.getSkill=function(){ return this.skill } //子类构造函数 function Son(name,sex,age,sno){ //调用父类的构造函数 从而继承父类的属性 Person.call(this,name,sex,age) this.sno=sno } //子类继承父类原型上的方法 Son.prototype=Object.create(Person.prototype) //完善子类的constructor指向 将Son的原型对象重新再指向构造函数本身 Son.prototype.constructor=Son //在子类身上添加方法 Son.prototype.doHomework=function(){ console.log('每天做十个小时作业') } let S1=new Son('小明','男',18,1001) console.log(S1)
首先就是写一个父类的构造函数,然后在函数里面写属性和方法,父类的方法是挂载在父类的原型上的,然后子类的构造函数里面可以通过call或者apply改变this指向,从而调用父类的构造函数,继承父类的属性,然后子类可以通过object.create的方法继承父类原型上的方法,最后要做的就是通过原型对象的constructor将子类原型对象重新指向子类构造函数本身.
原型链
原型.每一个函数都有一个原型对象prototype,他的值是一个对象;
每个实例对象里面都有一个隐式原型_proto_,他指向构造函数的原型对象prototype
每一个原型对象里面都有一个构造器constructor,他指向函数本身.
原型链就是每一个构造函数有对应的原型对象,而原型对象又可以是另一个构造函数所创建的实例,这个创建出来的实例也有自己对应的原型对象,这种关系层层递进,所构成的链式结构就是原型链.
原型链也有自己的查找规则,当一个对象在查找标识符时,会先在对象自身身上找,没找到就沿着原型链逐层向上找,直到找到null
说到原型链的查找规则,我们平常说的万物皆空也可以从这里解释,因为不管哪一种数据类型,只要沿着原型链往上找,最终都能找到Object,Object再往上找就是null.
This指向
主要有7种this指向
1.一般函数中的this.谁调用指向谁
2.构造函数中的this,指向实例化的那个对象
3.对象中的this,谁调用就指向谁
4.事件处理函数中的this,指向事件源
5.定时器里面的this,指向window
6.箭头函数中的this,指向定义时的作用域
7.全局的this,指向window
设计模式
Call、Apply、Bind的用法和区别
call,apply,bind的作用就是改变函数运行是this的指向
call,apply他们两个在用法上几乎相同,唯一的差别就在于,在传递参数时,call接收的参数是单独的变量,而apply接收的参数时一个数组
bind和call以及apply 的区别在于bind返回值是一个函数,便于稍后调用,而apply,call则是立即调用
New实现
1.创建一个空的对象
2.将this挂载在这个空对象上(为了继承函数的原型)
3.给对象添加属性和方法
4.返回一个对象
- 以构造器的prototype属性为原型,创建新对象
- 将this和调用参数传给构造器执行
- 如果构造器没有手动返回对象,则返回第一步创建的对象
防抖节流
防抖
短时间内多次触发,最终在停止触发后的某个指定时间执行一次
// 实现滚动条的防抖功能
// 在第一次触发事件的时候,不会立即执行函数,而是给出一个delay值,比如1000ms
// 如果在在1000ms之内没有再次触发该事件,就执行函数
// 如果在1000ms之内再次触发该事件,就清除当前的计时器,重新开始计时
// fn是需要防抖的函数,daley是防抖指定的时间
function debounce(fn,delay){
let timer = null //借助闭包解决防抖问题
return function(){
if(timer){
clearTimeout(timer)
timer=setTimeout(fn,delay)// 进入该分支说明正在计时,所以就把之前正在计时的计时器关掉,然后重新开始计时
}else{
timer=setTimeout(fn,delay) // 进入该分支,说明timer为空,就是没有在计时.所以就进入一个计时
}
}
function showTop(){
let scrollTop=document.body.scrollTop || document.documentElement.scrollTop
}
window.onscroll==debounce(showTop,<