内容较多,建议查看目录,方便食用
高频
React和Vue的区别
通常解法:vue是采用指令结合vue-loader实现构件用户界面的渐进式框架,React是采用JSX构件用户界面的组件化开发
详细解法:在渲染界面的时候DOM操作是昂贵的,我们能做的最后就是减少DOM操作。Vue和React都使用虚拟DOM来实现,并且二者工作一样好
相同点:
- 都支持服务端渲染
- 都使用虚拟DOM实现
- 都有组件化开发,通过props参数进行父子组件之间的数据传递
- 只有框架的骨架,路由、状态管理等是分离的
- 都是JS的UI框架,都是数据驱动视图的
- 都支持native的方案,React的React native,Vue的weex
- 都有状态管理,React的redux,Vue的vuex
不同点:
- React严格上只针对MVC的view层,Vue则是MVVM模式
- 虚拟DOM不一样,Vue会跟踪每个组件的依赖关系,不需要重新渲染整个组件树
- 对于React而言,每当应用状态被改变时,全部组件都会重新渲染,所以需要shouldComponentUpdate生命周期方法来控制
- Vue实现了双向数据绑定,而React的数据流是单向的
- state对象在React中是不可变的,需要用setState方法更新状态。
- Vue中数据由data属性在Vue对象中管理
什么时候用Vue什么时候用React?
Vue语法简单,开发速度快,灵活,v指令极大地简化了开发;React最大的特色就是强大的社区支持,是由facebook出品的。对移动端的构建很友好,React的版本迁移比Vue更好一些
React的优点
- 1、声明式的设计可以轻松构建应用
- 2、采用虚拟DOM减少与真实DOM的交互,极大的提高了性能
- 3、使用JS的扩展语言JSX代码可读性很好
- 4、可以与已有的库和框架进行很好的配合
- 5、单向数据流的设计减少了重复代码
- 6、组件化的设计可以很好的实现代码复用
- 7、faceBook出品,庞大的社区支持
React怎么获取真实DOM
- 通过在标签中添加ref属性
class Index extends Component {onClick(event){const inputDom = this.refs.submit;console.log(inputDom);}render(){return (<div><input ref='submit' type='button' value='getDom' onClick={this.onClick.bind(this)}/></div>)}
- 在标签中写入一个匿名函数
class Input extends Component {componentDidMount() {console.log(this.textInput);}render() {return (<inputtype="text"ref={input => this.textInput = input}/>);}
- 在标签中加入一个回调函数
class CustomTextInput extends Component {constructor(props) {super(props);this.textInput = React.createRef();}render() {return (<inputtype="text"ref={this.textInput}/>);}
new操作符
调用new会发生四件事
- 创建一个新对象
- 连接原型
- 改变this指向
- 返回新对象
function Person(name){this.name = name,this.age = 23
}
function myNew(Con, ...arg){//创建一个新对象 let obj = Object.creat(Con.prototype)//改变this的指向let res = Con.apply(obj, arg)return res instanceof Object ? res : obj
}
var per = myNew(Person, "miruo")
实现一个Instanceof
instanceof的机制:A instanceof B,在A的原型链上寻找B.prototype,找得到返回true,找不到返回false。但是instanceof不能准确判断基础数据类型,只能判断引用数据类型
function myInstanceof(left, right){let pro = right.prototypeleft = left.__proto__while(left !== null){if(left == pro){return true}else{left = left.__proto__}}return false
}
TS/JS
TS比JS更可靠,TS引入类型定义和编译器,可以避免JS大多数runtime错误,更可靠,易维护,更清晰。TS中显式类型声明可以提升代码的可读性,代码校验全部交给编译器负责。TS其实是JS的超集,可以在TS代码中混合使用任何JS库和代码。TS泛型其实就是让一个组件支持多种类型,在定义函数、接口或者类时,不预先指定具体类型,而是在使用的时候再指定类型限制的一种特性。
Less
Less时CSS的预处理语言,增加了变量、混合、函数等功能,让CSS更容易维护,方便制作主题,扩充。
怎么理解restful
REST就是表现层状态转移的缩写。把资源具体呈现出来的形式就是“表现层”。URI只代表资源的实体,不代表形式。换句话说URI只代表资源的位置。具体的表现形式,是.html也好还是.txt也好应该在http的请求头中指定的字段表示。对于http来说其实是一个无状态的协议,也就是说状态其实是保存在服务器的,那么客户端要操作服务器就要想办法让服务器发生状态转移。而这种转移是建立在表现层的。而客户端用到的手段其实就是http协议,GET、POST、PUT、DELETE分别对应四种操作。那么其实restful架构就是每个URI代表一个资源,客户端和服务端之间传递这种资源的表现层,客户端通过四个http动词,对服务端的资源进行操作,实现“表现层状态转移”
rem和em有什么区别
二者都是相对大小,区别就在于em是相对于父级元素的大小。rem则是相对于html根元素的大小。
es6有哪些特性
let/const、promise、async/await、generator、箭头函数、解构、模板字符串等
箭头函数和普通函数有哪些区别
箭头函数使用起来更加的方便,箭头函数的this指针指向外部函数的指针。
animation(动画)、transition(过渡)、transform(变形)、translate(移动)
-
transition需要触发条件,不能自动执行。
-
transition触发一次只能执行一次,对此执行需要多次触发条件。
-
transition只能设置开始和结束两个状态,不能设置中间状态。
-
animation像flash动画一样,可以设置动画关键帧
-
animation不需要触发条件,页面加载完成后自动执行
介绍一下React
React是用JS构建快速响应大型web应用的首选方案,是一个JS库,主要用于构建ui。虚拟DOM最大限度减少与真实DOM的交互,使用JSX代码可读性很好。可以与已有的库和框架很好的配合。使用React构建组件使代码更容易得到复用可以很好的应用在大项目的开发过程中。单向数据流减少了重复的代码。轻松实现数据绑定。
React生命周期
React声明周期其实就是React组件从挂载到卸载的过程。组件挂载就是组件渲染到页面呈现。组件卸载就是从DOM中移除。对于类组件来说我们可以在组件挂载到卸载的不同阶段执行特殊的函数,就是生命周期函数。
- componentWillMount 组件将要挂载时触发,主要进行一些初始化工作,这时是可以修改state的
- componentDidMount 组件挂载完成时触发,这个阶段可以发起请求
- componentWillReceiveProps 组件将要接受props时触发
- shouldComponentUpdate 是否更新数据时触发,返回一个布尔值
- componentWillUpdate 组件将要更新时触发,做更新前的一些准备
- componentDidUpdate 组件更新完成时触发,可以访问或者修改DOM,也可以发请求
- componentWillUnmount 组件将要卸载时触发,清除一些监听和计时器啥的,做收尾工作
Vue生命周期
Vue实例从创建到销毁的过程就是Vue的生命周期,创建-初始化-模板编译-挂载DOM-渲染 更新-渲染 卸载等一系列操作。称之为Vue生命周期。
- new Vue() 实例化一个Vue实例
- beforeCreate
- beforeCreate完成后就进行数据的初始化,会定义data,方法以及事件,完成数据劫持,给组件配置观察者实例。
- created 这时已经拿到data以及方法,可以开始调用方法进行数据请求。
- beforeMount 相关的render函数首次被调用
- mounted 有初始值的DOM渲染完成
- beforeUpdate
- updated
- beforeDestroy
- destroyed
React函数组件和类组件的区别
函数组件没有生命周期,没有this,没有state,通过hooks改变state,但是性能比较好,不用实例化
类组件有生命周期,有this,有state,通过setState方法改变state,,需要实例化,性能没有函数组件好
‘’ == 0/‘0’ == 0/‘’ == {}
对于相等表达式来说,两边类型相同就直接比较,两边类型不同则两边都Number()再比较。如果是对象就先toString再Number(),对于表达式{}==true:实际上等价于ToPrimitive({}) == ToNumber(true),即Number({}.toString()) == Number(true)。所以上面三个分别返回true,true,false
==运算符规则
x == y
- x和y类型相同时,都为number时比较特殊。其中一个为NaN就返回false,-0==+0
- null == undefined 返回true
- 二者若一个number一个string就ToNumber(string)再进行比较
- 若其中一个时boolean就ToNumber(boolean)再进行比较
- 若其中一个是String/Number,另一个是Object。那么久ToPrimitive(Object)再进行比较
- 当两边都是Object时,比较的是引用,不是值。[] == []和{} == {}都返回false,就是因为引用不同。
ToPrimitive()就是先toString()再ToNumber()。[].toString()是空,再ToNumber就是0,{}.toString()返回[object Object],再ToNumber就是NaN。
构造器中没用super会怎么样
子类必须在构造方法中调用super函数,否则新建实例的时候会报错,因为子类自己的this对象也需要父类构造函数构造,才能得到父类同样的属性和方法。不调用super子类就得不到this
Http缓存详解
http缓存主要针对一些实时性要求不高的静态文件进行的缓存,往往存在浏览器端,防止一些请求重复访问服务器。
MVC和MVVM
MVC思想就是,控制器负责将Model的数据用View显示出来。换句话说是控制器里面把Model的数据赋值给View。Model负责对数据的获取和存放,也就是数据的管理者。而调用数据的就是控制器。而View简单来说就是我们看到的界面上的一切,View就是负责界面的绘制。MVVM相比于MVC多了个VM少了控制器。Model负责对数据的存取,然而我们除了存取还要进行解析,所谓解析,就是把原始数据转换成View可以用的数据。现在一些App越来越复杂,数据解析的工作完全交给控制器,控制器就会变得非常臃肿。而实际上控制器被设计出来也不是用于数据解析的。基于面向对象的思想,就创造出一个对象用于数据解析,VM就诞生了。VM相当于是C的秘书,VM进行数据解析,而C只需要知道解析后的结果就可以了。
控制器内把M的数据赋值给V,但是由于需要数据解析,就用VM当作C的秘书进行数据解析,C只需要知道解析结果,存在感低了
Vue双向绑定的原理
利用Object.defineProperty()这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现。采用数据劫持结合发布者-订阅者模式的方式,通过劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调.
Object.defineProperty与Proxy理解
Object.defineProperty与Proxy常常被用来做数据劫持,数据劫持就是在访问和修改某个属性时,通过一段代码对操作进行拦截,进行额外的操作或者修改返回结果。最典型的应用是双向数据绑定。数据劫持有时也应用在保持数据的不可变性而拦截对数据的修改操作。区别:
- Object.defineProperty是对对象的属性进行遍历然后修改,Proxy是监听整个对象
- Object.defineProperty不能监听数组,Proxy可以
- Object.defineProperty直接在原对象上进行修改,Proxy则是返回一个新对象,对新对象进行操作
mouseenter和mouseover的区别
- mouseenter无论鼠标指针穿过被选元素或其子元素都触发mouseenter。对应mouseout
- mouseover只有在鼠标穿过被选元素时,才触发mouseenter事件。对应mouseleave
CSS盒子模型
盒子模型就是用来装页面上元素的矩形区域,主要有两种
- 标准盒子模型
- IE盒子模型
标准盒子模型和IE盒子模型的区别在于对widtd的计算,标准盒子模型的宽度就是content的宽度;IE盒子模型的宽度是content+padding+border
- 那么怎么设置这两种盒子模型 ?
通过CSS提供的box-sizing,box-sizing:content-box表示标准盒子模型 ;box-sizing:border-box表示IE盒子模型 - 为什么会有两种盒子模型?
在微软的市场份额达到百分之80的时候,他们想自己制定一套浏览器标准,其中就包括IE盒子模型。但是其他的浏览器厂商并不同意微软的做法,就采用了W3C的标准。这就导致IE浏览器和其他浏览器盒子模型不同,但是一些老网站仍然是IE盒子模型,所以就把IE盒子模型保留了下来。 - 应用场景:如果我们想设置两个子容器,使其都左浮动,然后宽度都设置为50%,然后给一点padding,运行就会发现两个子容器换行了,这时就可以用标准盒子模型了。
link和import的区别/src与href的区别
link和import的区别:
- link是属于html标签,而@import是css提供的,只能加载CSS
- 页面加载时link就加载,而@import引入的是在页面加载结束后加载
- link权重高于import
- link支持使用JS控制DOM改变样式,@import不允许
src与href的区别:
- href是超文本引用,引用和页面关联,表示在当前元素和引用资源之间建立联系
- src表示引用资源替换当前元素,会将指向资源下载并应用到当前文档中
Flex布局
常见的布局方案对于一些特殊的布局很不方便,比如垂直居中。Flex非常灵活,Flex布局的属性大致分为容器属性和元素属性
容器属性:
- flex-direction: row | row-reverse | column | column-reverse决定主轴方向
- flex-wrap: nowarp | wrap | wrap-reverse 决定换行规则
- justify-content: 水平主轴对其方式
- align-items: 垂直轴线对齐方式
元素属性:
- order: 定义元素排列顺序,序号小的靠前
- flex-grow: 定义项目放大比例,取值为1是自适应,取值为0则没大小
- flex-shrink: 定义项目缩小比例,空间不足时缩小,取值0则不缩小
- flex-basis: 定义了在分配多余空间时项目占据的空间,设置为auto则根据内容判断大小,可以设置为一个具体的值,如100px
- flex: 是上面三种属性的缩写,默认值0 1 auto
- align-self: 允许单个项目与其他项目不一样的对其方式,可以覆盖align-item默认值是auto表示继承父元素的align-items
BFC(块级格式化上下文)
可形成独立渲染区域,通常用于清除浮动,防止margin重叠。BFC是一个独立的容器,容器内元素不会影响外面,计算高度时,浮动元素也计算在内。
BFC形成条件:
- 根元素
- 浮动元素
- 绝对定位元素absolute、fixed
- display为inline-block、table-cell、table-caption、flex、inline-flex
- overflow 不为visible的元素
BFC应用场景:
- 防止margin重叠
- 自适应两栏布局,left浮动,right设置overflow: hidden,这样不会重叠
- 清除浮动
块级元素和行级元素
**块元素:**独占一行,并且自动填满父元素,可以设置盒子模型的属性;主要有:div、p、h1-6、ol、ul、table、form
**行元素:**不会独占一行,width和height会失效,垂直方向上的padding和margin会失效,只能容纳文本和其他行元素;主要有:a、em、strong、span、i、label、br
**行内块:**综合块级元素与行内元素的特性,可设宽高(默认是内容宽高),也可以设置内外边距;主要有img和input、textarea等,其实属于行元素
p是块级元素,但是不能包含除了p之外的其他块级元素;a是行内元素,但是可以包含它本身外的任意块元素
HTML5新标签
visibility = hidden, opacity=0, display: none
opacity=0:元素被隐藏,不改变布局,可以触发绑定事件
visibility = hidden:元素被隐藏,不改变布局,不可以出发绑定事件
display: none:元素被隐藏,会改变布局,不可触发点击事件,可以理解成该元素被删除了
双边距重叠(外边距重叠)
多个相邻普通流的块元素垂直方向上的margin会重叠
- 两个正数取较大的
- 两个负数取绝对值大的
- 一正一负取二者的和
清除浮动
- 在浮动元素后使用一个带clear属性的空元素
- 使用CSS的overflow属性,给浮动元素的容器添加overflow:hidden或者overflow:auto清除浮动,添加overflow属性后浮动元素回到容器层,把容器高度撑开
- 给浮动元素后面的元素添加clear属性
- 给浮动的元素的容器添加浮动
- 使用CSS的:after属性,相当于在现元素的末尾添加一个看不见的块清除浮动
CSS选择器,样式优先级
- 样式优先级:!important > 内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式
- 内联样式>ID选择器>类选择器=属性选择器=伪类选择器>标签选择器=伪元素选择器
- 同一元素引用多个样式,排在后面的样式属性优先级高
- 样式选择器类型不同时:id选择器 > 类选择器 > 标签选择器
- 标签选择器存在层级关系,后代属性会覆盖祖先属性,继承的样式优先级比较低
- 属性选择器和伪类选择器优先级相同
grid网状布局
给div设置display: grid;那么这个div就是一个网状布局容器,此div的直接下一级元素称为项目。布局属性分为容器属性和项目属性。
容器属性:
- grid-template-columns 此属性设置每一列的列宽
- grid-template-rows 定义每一行的行高
- repeat grid-template-rows: 30px 30px 30px 等价于grid-template-rows: repeat(3, 30px)
- auto-fill关键字 grid-template-rows: repeat(auto-fill, 30px)表示自动填充30px的块直到容器装满
三栏布局
- 1、浮动加margin
- 2、定位
- 3、table
- 4、flex
- 5、grid
display属性详解
display也就是展示,通常用于定义元素生成显示框的类型:
- inline 默认值,元素会被显示为内联元素,无法设置width,height,不独占一行
- block 块级元素,前后有换行符,可以设置width,height,元素独占一行
- inline-block 行内块元素,可以设置width和height,不独占一行
- table 此元素会作为块级表格来显示(类似 ),表格前后带有换行符
- table-cell 此元素会作为一个表格单元格显示(类似 和 )
垂直居中的方法
三种方法:
- 1、首先想到的是对子元素设置left和top都是50%,这时子元素显示在父元素中心点的右下角。然后利用margin top和left负值为子元素大小的一半使其向左上方偏移至水平垂直居中。
- 2、利用calc可以直接设置top和left为(50%-子元素高或宽的一半)
但是上面两种方式都必须知道子元素的大小,下面的方法比较好
- 3、transform的translate属性也可以设置百分比,其是相对于自身的宽和高,所以可以讲translate设置为-50%,就可以做到居中了。
- 4、第三种就是将子元素四个位置都设置为零,margin设置为auto实现垂直居中。如果不把四个位置设置为0那么margin:auto将被视为margin: 0,如果不设置margin: auto,由于left和top的优先级高,子元素将显示在左上角。
- 5、还有一种是利用table的属性,将父元素设置为display: table-cell然后使用text-align: center;vertical-align: middle;使单元格里的内容水平垂直居中,当然子元素也要设置为display: inline-block
- 6、flex布局,父元素display: flex; justify-content: center; align-items: center
- 7、父元素grid布局,父元素display: grid; 子元素justify-self: center; align-item: center。但由于兼容性不好没有广泛使用
标签语义化
header、footer、nav、article、aside、section主要作用就是提升用户体验、使代码更具有可读性,使代码结构更清晰
Promise和async/await的区别
async/await是寄生于Promise和generator的语法糖。
- Promise是ES6的,async/await是ES7的
- async/await相对于Promise写法上更加优雅
- promise错误可以通过catch来捕捉,建议尾部捕获错误,async/await既可以用.then又可以用try-catch捕捉
HTTP简介
HTTP(超文本传输协议),是从万维网服务器传输超文本到本地浏览器的传送协议。浏览器作为HTTP客户端通过URL向HTTP服务器即web服务器发送请求。HTTP三要点:
- 无连接 每次连接只处理一个请求,结束就断开
- 媒体独立 只要客户端和服务器知道如何处理内容,任何数据类型都可以发送
- 无状态 无状态,不会记忆传输过的数据。下次要重新请求
HTTP请求报文
一个HTTP请求由:请求行、请求头、请求体组成
- 请求行由请求方法、URL、协议版本组成
- 请求头,由若干属性组成,属性名:属性值 的形式。服务端通过请求头获取客户端的信息
- 请求体,就是请求的数据,请求体可以传递请求参数
常见请求头字段
- Accept 告诉服务端可以接受的数据类型,可以为一个或多个MIME类型
- Cookie Cookie就是通过HTTP请求头携带过去的
- Referer 表示请求是从哪个URL过来的
- Cache-Control 要求服务端返回的内容可以存的时间,设置为no-cache则希望响应内容不被客户端缓存,max-age=10则是10秒
- Connection 控制两端的连接状态,Connection: keep-alive连接不会关闭,继续访问还用这条连接
- Host通常在URL中提取出来,指定被请求资源的主机和端口号
- User-Agent 告诉服务器客户端使用的操作系统和浏览器版本
- Accept-Language 浏览器申明自己接受的语言
HTTP响应报文
一个HTTP响应由:响应行、响应头、响应体组成
- 响应行由协议版本、状态码及状态描述组成
- 响应头,由若干属性组成,属性名:属性值 的形式。
- 响应体,就是得到的数据
常见响应头字段
- Cache-Control 服务器告诉客户端如何控制响应内容的缓存
- expires 响应过期的时间
- Last-Modified 请求资源的最后修改时间
- ETag 一个代表资源版本的属性,资源改变这个属性也会改变
- Location 是一个URL地址,让页面重定向到另一个页面,就是让其向另一个页面发请求
- Set-Cookie 服务端可以设置客户端的Cookie 比如:Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
- Accept-Ranges 表示服务器是否支持指定范围的请求
- Access-Control-Allow-Origin 设置允许访问该资源的域
- Access-Control-Allow-Methods 允许哪些方法来访问
- Age 从原始服务器到代理缓存形成的预估时间
- Connection 同上
- Content-Length 响应体的长度
- Content-Type 返回内容的MIME类型
- Date 原始服务器消息发出的时间
- Server web服务器软件名称
Cache-Control常见取值
- public 这个请求返回的内容所经过的路径无论是代理服务器还是客户端都可以缓存内容
- private 发起请求的浏览器才能使用返回数据的缓存
- no-cache 每次发起请求都要去服务器验证,服务器返回可以使用缓存才可以真正使用本地缓存
- max-age 资源时限
- no-store 响应不被缓存,与no-cache不同,no-cache会缓存,只是每次都要验证
Cache-Control与expires优先级
expires返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大
HTTP1.0
同一时间同一域名的请求数量有限制,超过限制数目请求会被阻塞。只保持短暂连接,每次请求都需要建立TCP连接,完成请求立即断开并且不记录过去请求
HTTP1.1
默认使用持久连接,不声明Connection: keep-alive也可以使TCP不关闭,可以被多个请求复用。同一TCP连接可同时发送多个请求,但是一个TCP中所有数据按次序进行。一个一个的处理。如果前面的处理的慢,后面的就会阻塞,就是队头阻塞。
HTTP2
HTTP2性能增强的核心在于二进制分帧层,它定义了如何封装HTTP消息并在客户端和服务端之间进行传输。HTTP1.x以换行符作为纯文本的分隔符,而HTTP2将所有传输信息分割成更小的消息和帧,并对他们采用二进制编码。
JS
1、解决异步回调地狱
- Promise
- generator
- async/await
2、事件流
事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
- addEventListener是DOM2级事件新增的指定事件处理程序的操作,接收三个参数
- 要处理的事件名、作为事件处理程序的函数、一个布尔值
- 最后的布尔值如果是true表示在捕获阶段调用事件处理程序;如果是false表示在冒泡阶段调用事件处理程序
- IE只支持事件冒泡
3、事件委托
事件委托指的是不直接在DOM上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发
4、图片懒加载和预加载
- 预加载:提前加载图片,当用户需要查看时直接从缓存渲染
- 懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数
- 懒加载对服务器前端有一定缓解压力的作用,预加载会增加服务器前端的压力
5、JS的new操作符做了哪些事情
- 创建一个空对象
- 将对象的原型设置为构造函数的原型
- 将构造函数的this指向这个新对象
6、JS的各种位置
- clientHeight:表示可视区域的高度,不包含border和滚动条
- offsetHeight:表示可视区域的高度,包括border和滚动条
- scrollHeight:表示所有区域高度,包含了因为滚动被隐藏的部分
- clientTop:表示边框border的厚度,在未指定的情况下一般为零
- scrollTop:滚动后被隐藏的高度获取对象相对于由offsetParent属性指定的父坐标距离顶端的高度
7、异步加载JS的方法
- defer:defer是在浏览器加载完之后执行JS代码,并按照加载顺序执行代码
- async:async是在加载完之后立即执行,特点是乱序执行,因为每个JS代码加载时间不同
8、如何理解前端模块化
就是把复杂的文件编程一个一个独立的模块,比如JS文件分成独立的模块有利于重用和维护,这就会有模块间的依赖问题
所以有了commonJS规范,AMD,CMD规范等等,以及用于JS打包的工具webpack
- CommonJS:开始于服务器端模块化,同步定义模块化,每个模块都是一个独立作用域,模块输出modules.exports模块加载require()引入模块
- AMD:异步模块定义主要用于解决两个问题:被依赖的文件要早加载,加载时浏览器停止渲染,文件越多,页面失去响应的时间越长
9、JS监听对象属性的改变
- 在ES5中可以通过Object.defineProperty来实现已有属性的监听
- 在ES6中可以通过Proxy来实现
Object.defineProperty(obj, prop, descriptor)
- obj需要定义属性的对象
- prop需要定义的属性
- descriptor属性描述符
10、事件模型,DOM0级和DOM2级有什么区别,DOM分级
- JS DOM事件流存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段
- DOM节点添加事件监听函数addEventListener(事件名,触发函数,布尔值)
- 布尔值为true监听添加在捕获阶段,布尔值为false监听添加在冒泡阶段
事件模型常用方法:
- event.stopPropagation:阻止捕获和冒泡阶段中,当前事件的进一步传播
- event.preventDefault:取消该事件而不停止事件的进一步传播
11、跨域
跨域问题是由浏览器的安全限制-同源策略引起的。两个地址协议域名和端口都相同则是同域,有一个不同就是不同域。浏览器想要执行不同域的浏览器的脚本就要进行跨域操作。注意跨域并不是指请求发不出去而是发出去了,并且服务器接收到了并返回数据,只不过结果被浏览器拦截了。
以下三种方式解决跨域问题:
12、CORS(跨来源资源共享)
**原理:**简单来说就是浏览器和服务器利用自定义的http头部进行沟通,从而决定请求或者响应是否成功。服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的,如果浏览器检测到相应的控制就允许跨域。只需在后台中加上响应头来允许跨域。浏览器将CORS跨域请求分为简单请求(get,post,head)和非简单请求(其他方法)。
- 简单请求的话浏览器直接发送CORS请求,在头信息增加一个Origin字段说明本次请求的来源。服务器根据这个值判断是否同意请求。响应头中的Access-Control-Allow-Origin取值决定是否同意请求。
- 对于非简单请求需要先发送预检请求,询问服务器支持的HTTP方法,请求中包含Origin
13、反向代理解决跨域
服务器与服务器之间不存在跨域问题,所以通过设置本地服务器去访问目标服务器,然后本地服务器返回数据不存在跨域
14、JSONP解决跨域
原理就是src属性是不存在跨域问题的,可以自定义一个script标签,然后手动设置src属性,实现跨域。但是缺点是只能发送get请求
15、XSS(跨站脚本攻击)
简单来说就是在用户的浏览器中执行了攻击者制定的脚本。用户执行攻击者的脚本,将自己的cookie发送到了攻击者的网站。攻击者获得用户信息,发送到了攻击者自己的网站
XSS防御机制:对输入进行过滤,对输出进行编码。对提交的所有内容进行过滤,过滤掉会导致脚本执行的相关内容;在输出数据之前对潜在威胁的字符进行编码、转义;对cookie设置HttpOnly属性,在浏览器的document对象中就看不到cookie了,JS脚本就不能读取到cookie,但浏览器还是能正常使用cookie
16、CSRF(跨站请求伪造)
简单来说就是攻击者盗用受害者的身份,以受害者的名义发送恶意请求
原理:用户登录可信任网站A,登录状态下访问了攻击者网站B,网站B强制用户给网站A发送请求,执行网站B的恶意代码
CSRF防御机制:
- 1.验证Http Referer字段:简单来说这个字段就是请求头中记录请求来源地址的,服务器可以通过对Referer字段进行验证来判断发送请求的网站是否合法
- 2.在请求地址添加token: 用户发送请求的验证信息都存在于cookie,攻击者利用用户的cookie来通过安全验证。所以只要在cookie之外,http请求中加入一个随机的token,并在服务器端设置拦截器验证token。token不正确就可能是CSRF攻击
- 3.在http头中自定义属性并验证:并不是把token以参数的形式置于http请求中,而是放到http头中自定义的属性中。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个Http头属性,并把token值放入其中。同时通过XMLHttpRequest请求的地址不会被记录到浏览器的地址栏
**token:**token可以在用户登录后产生并存放在session中,然后每次请求时把token从session中拿出,与请求中的token进行比对。难点在于如何把token以参数的形式加入请求。对于get请求,token将附在请求地址之后。对于post请求来说,要在form最后加上token相关的。但是有一个缺点就是难以保证token本身的安全,比如一些支持用户自己发表内容的网站。黑客可以在上面发送个人网站的网址就可以获得token
17、Web worker
Web worker为JS创造了多线程的环境,允许主线程创建worker线程,并分配一些任务给后者,主线程运行的同时,worker线程在后台运行。worker存在于一个不同的线程,它和主线程互不干扰,可以把处理大量数据的逻辑计算放在worker里,主线程就会很流畅。worker线程一旦新建成功,就会始终运行,不会被主线程上的活动打断。有利于随时响应主线程的通信。但是这也造成worker比较消耗资源,所以一旦使用完就要关闭。
18、防抖和节流
- 防抖:问题在于快速点击按键时,无论点击多快,只要点了一次,日志就打印一次,想要在快速点击的过程中只让最后一次产生效果,就要防抖
- 节流:在多次点击的情况下保证每隔一段固定时间执行一次点击事件触发的函数
19、var let const区别
var一般用于声明变量,是函数作用域的,但是因为var存在变量提升机制,所以在ES6新增了let和const;let和const都是块级作用域的,不存在变量提升机制,因为暂时性死区的特性,let在使用前必须进行声明。而const必须 初始化,一般用来声明常量。另外const定义的是一个对象,存的仅仅是对象的引用。
20、判断是否同域
- http://www.a.com/a.js http://www.a.com/b.js 同域
- http://www.a.com/lab/a.js http://www.a.com/script/b.js 同域,文件夹不同
- http://www.a.com:8000/a.js http://www.a.com/b.js 不同域,端口不同
- http://www.a.com/a.js https://www.a.com/b.js 不同域,协议不同
- http://www.a.com/a.js http://script.a.com/b.js 不同域,主域相同,子域不同
- http://www.a.com/a.js http://a.com/b.js 不同域,不同二级域名
parseInt()使用方法
parseInt(string, radix) 接受两个参数,第一个参数时要解析的字符串,第二个参数是要转化的进制,要点如下:
- 只返回字符串中第一个数字
- 允许前导和尾随空格
- 如果第一个字符不能转换为数字就输出NaN
Math.toFixed/Math.round/toPrecision
- Math.toFixed(n) n是几就保留几位小数
- Math.round(1.2)//1 四舍五入到最近的整数
- 13.45toPrecision(3)//13.4 返回指定长度的数值字符串
||和&&的判定规则
|| 前面的值为true,返回true
|| 前面的值为false,返回后面的
&& 前面的值为true,返回后面的
&& 前面的值为false,返回false
scrollWidth、offsetWidth、clientWidth
- scrollWidth 内容+内边距+溢出尺寸
- offsetWidth 内容+内边距+边框+滚动条
- clientWidth 内容+内边距
- scrollWidth 网页正文全文宽
- scrollHeight 网页正文全文高
- scrollTop 网页被卷去的高
- scrollLeft 网页被卷去的左
document对象和window对象的区别
- 指代不同:document对象代表给定浏览器窗口中的HTML文档。window表示浏览器中打开的窗口
- 作用不同:使用document可以对html文档进行检查修改或添加内容并处理该文档内部的事件;浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。
- 使用方式不同:document对象可以通过window对象的document属性引用或直接引用。而window对象没有应用于window对象的公开标准。
前端性能优化方案
1、减少http请求数
一个完整的http请求需要进行DNS解析、tcp三次握手建立连接、发送请求、服务端响应处理、客户端解析等一系列步骤。如果HTTP请求过多肯定会影响性能,可以将多个小文件合并成一个大文件减少请求数量
2、使用HTTP2
HTTP2有二进制分帧、首部压缩、服务端推送、多路复用、请求优先级等优点
3、静态资源使用CDN
CDN可以根据网络流量、各节点连接数、负载情况、用户距离、响应时间等将用户请求重新导向至离用户最近的服务节点上。可以使用户就近得到内容,解决网络拥挤的情况,提高响应速度
4、CSS放在文件头部,JS放在文件底部
JS的加载会阻塞页面的渲染,JS放在前面会使页面空白。而CSS放在头部是为了防止出现没有CSS的页面状态。会很丑陋
5、善用缓存,不重复加载资源
强缓存、协商缓存
6、减少重绘和重排
- 改变样式属性时尽量使用class减少与DOM的交互
- 频繁的修改可以现让元素脱离文档流,操作完之后再改回去,这样只会触发一次回流。绝对定位或者display:none
- 将原始元素拷贝到一个独立的节点,操作完之后覆盖之前的