基本信息
可以的,为什么会这样呢?这是由于对象或者数组属于引用数据类。
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
1.你觉得前端工程师的价值体现在哪?
为简化用户使用提供技术支持(交互部分)
为多个浏览器兼容性提供支持
为提高用户浏览速度(浏览器性能)提供支持
为跨平台或者其他基于webkit或者其他渲染引擎的应用提供支持
为展示数据提供支持(数据接口)
HTML/HTML5
1.知道语义化吗?说说你理解的语义化,如果是你,平时会怎么做来保证语义化?
像html5的新的标签header,footer,section等就是语义化
一方面,语义化就是让计算机能够快读的读懂内容,高效的处理信息,可以对搜索引擎更友好
另一方面,便于与他人的协作,他人通过读代码就可以理解你网页标签的意义
去掉或者丢失样式的时候能够让页面呈现出清晰的结构
有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重
方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义方式来渲染网页
便于团队开发和维护,语义化更具有可读性,是下一步把网页的重要动向,遵循W3C标准的团队都要遵循这个标准,减少差异化
2.介绍HTML5的新特性
新的DOCTYPE声明<!DOCTYPE html>
完全支持css3
video和audio
本地存储
语义化表圈
canvas
新事件如 ondrag onresize
3.如果解决ajax无法后退的问题?
html5里引入了新的API,即:history.pushState,history.replaceState
可以通过pushState和replaceSate接口浏览器历史,并且改变当前页面的URL
onpopstate监听后退
4.websocket和ajax轮询
websocket是html5中提出的新的协议,可以实现客户端与服务器的通信,实现服务器的推送功能
优点是,只要简历一次连接,就可以连续不断的得到服务器推送消息,节省带宽和服务器端的压力。
ajax轮询模拟常连接就是每隔一段时间(0.5s)就向服务器发起ajax请求,查询服务器是否有数据更新
缺点就是,每次都要建立HTTP连接,即使需要传输的数据非常少,浪费带宽
5.web worker和websocket
worker主线程:
通过worker = new worker(url)加载一个js文件来创建一个worker,同时返回一个worker实例
通过worker.postMessage(data)方法来向worker发送数据。
绑定worker.onmessage方法来接收worder发送过来的数据
可以使用worker.terminate()来终止一个worder的执行。
websocket
是web应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个HTML5协议,websocket链接是持久的,通过在客户端和服务器之间保持双向链接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定的时间去轮询
6.Doctype作用?严格模式与混杂模式如果区分?意义?
<!DOCTYPE>声明位于文档的最前面,处于标签之前。告知浏览器以何种模式来渲染文档
严格模式的排版和js运作模式是 以该浏览器支持的最高标准运行
在混杂模式中,页面已宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作
DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现
7.Doctype多少种文档类型?
该标签可声明三种DTD类型,分别表示严格版本、过渡版本以及基于框架的HTML文档
HTML4.01规定了三种文档类型:Strict, Transitional以及Frameset
XHTML 1.0规定了三种XML文档类型:Strict, Transitional以及Franmeset
Standards(标准)模式(也就是严格呈现模式)用于呈现遵循最新标签的网页,而Quirks(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页
8.HTML与XHTML,有什么区别?
所有的标签必须要有一个相应的结束标签
所有标签的元素和属性的名字都必须使用小写
所有的XML标记都必须合理嵌套
所有的属性必须引号“”括起来
把所有的<和&特殊符号用编码表示
给所有属性赋一个值
不要在注释内容使用'--'
图片必须要有说明文字
CSS
1.content-box和border-box,为什么看起来content-box更合理,但还是经常使用border-box?
content-box是W3C的标准盒模型 元素宽度+padding+border
border-box 是ie的怪异盒模型,他的元素宽度等于内容宽度 内容宽度包含了padding和border
比如有时候在元素基础上添加内边距padding或border会将布局撑破 但是使用border-box就可以轻松完成
2.实现三个DIV等分排在一行(考察border-box)
1.设置border-box width 33.33%
2.flexbox flex:1
3.实现两栏布局有哪些方法
方法一:
*{
margin: 0;
padding:0;
}html,body{height: 100%;}#left{width: 300%;height: 100%;
float: left;}#right{height: 100%;margin-left: 300px;background-color: #eee;}
方法二:
*{margin: 0;padding: 0;}html,body{height: 100%;}#left{width: 300px;height: 100%;
float: left;}#right{height: 100%;overflow: hidden;backrgound-color: #eee;}
以上第二种方法,利用创建一个新的BFC(块级格式化剩下文)来防止文字环绕的原理来实现的。BFC就是一个相对独立的布局环境,它内部元素的布局不受外面布局的影响。
它可以通过下一任和一种方式来创建
float的值不为none
position的值不为static 或者 relative
display的值为table-cell,table-caption,inline-block,flex,或者inline-flex其中一个
overflow的值不为visible
方法三:flex布局
4.flex属性值是多少?
flex属性是flex-grow,flex-shrink 和 flex-basis的简写
flex-grow属性定义项目的放大比例,默认为0
flex-shrink属性定义了项目的缩小比例,默认为1
flex-basis属性定义了项目的固定空间
5.怎么实现一个DIV左上角到右下角的移动,有哪些方法?怎么实现?
改变left值为window宽度-div宽度 top值为window高度=div高度
jquery的animate方法
css3的transition
6.垂直居中
单行行内元素
可以设置padding-top,padding-bottom
将height和line-height设为相等
多行行内元素
可以将元素转为tabel样式,再设置vertical-align:middle;
使用flex布局
块级元素
已知高度绝对定位负边距
未知高度transform:translateY(-50%);
flex布局
display: flex;
justify-content: center;
aligin-items: center;
7.rem 和 em的区别?
em相对于父元素,rem相对于根元素
8.清除浮动
利用clear属性进行清理
父容器结尾插入空标签
<div style="clear: both;"></div>
利用css伪元素:
.clearfix:after { content: "."; height: 0; visibility: hidden; display: block; clear: both;}
将父容器形成BFC
BFC能清理浮动主要运用的是它的布局规则:
内部的Box会在垂直方向,一个接一个的放置
box垂直方向的距离由margin决定。属于同一个BFC的两个相邻box的margin会发生重叠
每个元素margin box的左边,与包含快border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此
BFC的区域不会与float box重叠
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也是如此
计算BFC的高度时,浮动元素也参与计算
浮动清理利用的主要是第六条规则,只要将父容器出发为BFC,就可以实现包含的效果。那么出发BFC有哪种方法?
根元素
float属性不为noe
position为absolute或fixed
display为inline-block,table-cell,table-caption,flex,inline-flex
overflow不为visible
9.position的值, relative和absolute分别是相对于谁进行定位的?
relative:相对定位,相对于自己本身在正常文档流中的位置进行定位。
absolute:生成绝对定位,相对于最近一级定位不为static的父元素进行定位。
fixed: (老版本IE不支持)生成绝对定位,相对于浏览器窗口或者frame进行定位。
static:默认值,没有定位,元素出现在正常的文档流中。
sticky:生成粘性定位的元素,容器的位置根据正常文档流计算得出。
10.CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?
选择符:
id选择器(#myId)
类选择器(.myClassName)
标签选择器(div,p,h1)
相邻选择器(h1 + p)
子选择器(ul > li)
后代选择器(li a)
通配符选择器(*)
属性选择器(button[disabled="true"])
伪类选择器(a:hover,li:nth-child)
优先级:
!important > 行内样式(比重1000) > id(比重100) > class/属性(比重10) > tag / 伪类(比重1);
伪类和伪元素区别:
a:hover,li:nth-child
伪元素:li:before、:after,:first-letter,:first-line,:selecton
11.介绍sass
定义变量css嵌套,允许在代码中使用算式,支持if判断for循环
12.transition 和 margin的百分比根据什么计算?
transition是相对于自身;margin相对于参照物
13.实现一个秒针绕一点转动的效果
animation: move 60s infinite steps(60); /*设置旋转的中心点为中间底部*/
transform-origin: center bottom; /*旋转从0度到360度*/
@keyframes move {
from {
transform: rotate(0deg); }
to {
transform: rotate(360deg); }
}
14.display:none和visibility:hidden的区别?
display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。
15.CSS中link 和@import的区别是?
link属于HTML标签,而@import是CSS提供的;
页面被加载的时,link会同时被加载,而@import被引用的CSS会等到引用它的CSS文件被加载完再加载;
import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
link方式的样式的权重 高于@import的权重.
16.对BFC规范的理解?
BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的margin会发生折叠。
(W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行布局,以及与其他元素的关系和相互作用。
JS
1.介绍一下闭包和闭包常用场景?
使用闭包主要为了设计私有的方法和变量,闭包的有点事可以避免变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念。
闭包有三个特性:
函数嵌套函数
函数内部可以引用外部的参数和变量
参数和变量不会被垃圾回收机制回收
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见方式,就是在一个函数的内部创建另一个函数
应用场景,设置私有变量的方法
不适用场景:返回闭包的函数是个非常大的函数
闭包的缺点就是常驻内存,会增大内存使用量,使用不当会造成内存泄漏
2.为什么会出现闭包这种东西?解决了什么问题?
受javascript链式作用域链的影响,父级变量中无法访问到子级的变量值
3.介绍一下你所了解的作用域链,作用域链的尽头是什么?为什么?
每一个函数都有一个作用域,比如创建了一个函数,函数里面又包含了一个函数,那么现在又三个作用域,这样就形成了一个作用域链
作用域的特点就是,先在自己的变量范围中查找,如果找不到,就会沿着作用域链网上找
4.ajax简历的过程是怎样的,主要用到哪些状态码?
创建XMLHttpRequest对象,也就是创建一个异步调用对象
创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
设置响应HTTP请求状态变化函数
发送HTTP请求
获取异步调用返回的数据
使用javascript和DOM实现局部刷新
varxmlHttp =new XMLHttpRequest();
xmlHttp.open('GET','demo.php','true');
xmlHttp.send()
xmlHttp.onreadystatechange =function(){
if(xmlHttp.readyState === 4 & xmlHttp.status === 200){
}
}
5.使用promise封装
function getJSON(url){
returnnewPromise(function(resolve, reject){
varXHR =new XMLHttpRequest();
XHR.open('GET', url,true);
XHR.send();
XHR.onreadystatechange =function() {
if(XHR.readerSate == 4){
if(XHR.status == 200){
try {
varresponse = JSON.parse(XHR.responseText);
resilve(response);
} cath(e) {
reject(e);
}
}else{
reject(new Error(XHR.statusText));
}
}
}
})
}
getJSON(url).then(res => console.log(res));
当前状态readystate
0代表未初始化,还没有调用open方法
1代表正在加载,open方法已被调用,但是send方法还没有被调用
2代表已加载完毕,send已被调用,请求以及开始
3代表交互中,服务器正在发送响应
4代表完成,响应发送完毕
常用状态码status
404没找到页面
403禁止访问
500内部服务器出错
200正常
304被又被修改(not modified)(服务器返回304状态,表示源文件没有被修改)
说说你还知道的其他状态码,状态码的存在解决了什么问题?
302/307 临时重定向
301 永久重定向
借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了什么错误
6.事件委托
利用冒泡原理,把时间加到父级上,触发执行效果
可以大量节省内存占用,减少事件注册
可以方便地动态添加和修改元素,不需要因为元素的改动而修改时间绑定
varul = document.querySelector('ul'); varlist = document.querySelectorAll('ul li');
ul.addEventListener('click',function(ev){
varev = ev || window.event;
vartarget = ev.target || ev.srcElemnt;
for(vari = 0, len = list.length; i < len; i++){
if(list[i] == target){
alert(i + "----" + target.innerHTML);
}
}
});
7.javascript的内存回收机制?
垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
一般使用标记清除方法 当变量进入环境标记为进入环境,离开环境标记为离开环境
还有引用计数方法
堆栈
stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小不定也不会自动释放
基本数据类型存放在栈中
引用类型 存放在堆内存中,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据
8.函数防抖和函数节流?
函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次
函数防抖的要点,也是要一个setTImeout来辅助实现。延迟执行需要跑的代码
如果方法多次触发,则要把上次记录的延迟执行代码用clearTimeout清掉,重新开始
如果计时完毕,没有方法进来访问触发,则执行代码
vartiemr =false;
document.getElementById(‘debounce’,onScrll =function(){
clearTimeout(timer);
timer = setTimeout(function(){
console.log('111')
}, 300);
}
9.javascript中的this是什么,有什么用,指向上面?
全局代码中的this是指向全局对象
作为对象的方法调用时指向调用这个函数的对象
作为构造函数指向创建的对象
使用apply和call设置this
10.判断数组有哪些方法?
a instanceof Array
a.constructor == Array
Object.protype.toString.call(a) == [Object Array]
11.严格模式的特性?
对javascript的语法和行为,都做了一些改变
全局变量必须显式的声明。
对象不能有重名的属性
函数必须声明在顶层
消除js语法的一些不合理,不严谨之处,减少一些怪异行为
消除代码运行的一些不安全之处,保证代码运行的安全
提高编译效率,增加运行速度
为未来新版本的js做好铺垫
12.js的原型链,如何实现继承?
function foo(){};
foo.prototype.z = 3;varobj =new foo();
obj.x = 1;
obj.y = 2;
obj.x //1obj.y//2obj.z//3
13.图片懒加载
当页面滚动的时间被触发->执行加载图片操作->判断图片是否在可视区域内->在,则动态将data-src的值赋予该图片
14.webpack常用到哪些功能?
设置入口
设置输出目录
设置loader
extract-text-webpack-plugin将css从js代码中抽出并合并
处理图片文字等功能
解析jsx解析bable
15.函数组合继承
原型继承,构造函数继承,call apply继承
varsuper =function(name){
this.name = name;
}
super.prototype.func1 =function() {console.log('func1')}varsub =function(name, age){
super.call(this, name);
this.age = age;
}
sub.prototype =newsuper()'
16.对作用域链的理解
作用域链的作用是保证执行环境里有权访问的变量和函数是有序耳朵,作用域链额变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的
17.js垃圾回收方法
标记清除(mark and sweep)
这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
引用计数(reference counting)
在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
18.js继承方式及其优缺点
原型链继承的缺点
一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数
借用构造函数(类试继承)
借用构造函数虽然解决了刚才两种问题,但是没有原型,则复用无从谈起,需要原型链+借用构造函数的模式,这种模式成为组合继承
组合式继承
组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,这样,即通过在原型上定义方法实现了函数复用,有保证每个实例都有它自己的属性
ES6
1.let和const的区别?
let声明的变量可以改变,值和类型都可以改变,没有限制
const声明的变量不得改变值
2.平时用了es6的哪些疼,和es5有什么不同?
let,const,箭头函数,字符串模板,class类,模块化,promise
ES5 reuqire,react,createclass
3.介绍promise
就是一个对象,用来传递异步操作的消息。有三种状态:pending(进行中),resolved(已完成)和rejected(失败)
有了promise对象,就可以将异步操作以同步操作的流程表示出来,避免了层层嵌套的回调函数
前端框架
模块化
1.使用模块化加载时,模块记载的顺序是怎么样的,如果不知道,根据已有的知识,加载顺序是怎么样的
commonjs 同步 循序执行
AMD 提前加载,不管是否调用模块,先解析所有模块require速度快 有可能浪费资源
CMD提前加载,在正真需要使用(依赖)模块时才解析该模块
seajs按需解析,性能比AMD差
框架问题
1.什么是MVVM,和MVC有什么区别,原理是什么?
mvc的界面和逻辑关联紧密,数据直接从数据库读取,必须通过controller来承上启下,通信都是单向的
mvvm的view 和 viewModel可以互相通信,界面数据从viewmodel中获取
2.父子组件通信
vue:父组件是通过props属性给子组件通信,在子组件里面emit,在父组件监听
react:props传递 父给子穿一个回调函数,将数据传给父亲处理
3.兄弟组件怎么通信的?
vuex 建立一个vue的实例,emit触发时间 on监听时间
redux 子A ->父->子B
4.生命周期有哪些,怎么用?
beforecreated: el 和 data并未初始化
created: 完成了 data数据的舒适化,el没有
beforeMount:完成了el 和 data初始化
mounted:完成挂载,updated,destroyed
浏览器
1.跨域通信有哪些解决方案?
JSONP:
由于同源策略的限制,XMLHttpRequest只允许请求当前资源(域名、协议、端口)的资源,script标签没有同源限制,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。
通过动态<script>元素使用,使用时为src制定一个跨域url。回调函数处理JSON数据
优点:兼容性好,简单易用,支持浏览器与服务器双向通信
缺点:只支持GET请求
varurl = "http://localhost:8080/crcp/rcp/t99eidt/testjson.do?jsonp=callbackfunction"; varscript = document.createElement('script');
script.setAttribute('src', url);//load javascript document.getElementsByTagName('head')[0].appendChild(script); //回调函数 function callbackfunction(data){
varhtml=JSON.stringify(data.RESULTSET);
alert(html);
}
CORS:
服务器端对于CORS的支持,只要就是通过设置Access-Control-Allow-Orgin来进行的。如果浏览器检测到响应的设置,就可以允许ajax进行跨域访问。
通过设置Access-Control-Allow-Orgin来允许跨域,cors可以用ajax发请求获取数据,但是兼容性没有jsonp好
通过修改document.domain来跨子域
将子域和主域的doucment.domain设为同一个主域,前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致
主域相同的使用document.domain
使用window.name来进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口的生命周期内,窗口载入的所有的页面都是共享一个window.name。每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的
使用HTML5中心引进的window.postMessage方法来跨域传送数据
还有flash,在服务器上设置代理页面等跨域方式。
2.移动端兼容问题
IOS移动端click时间300ms的延迟响应
一些情况下对非可点击元素如(label,span)监听click时间,ios下不会触发,css增加cursor:poiner就搞定了
3.XML和JSON的区别?
数据体积方面:JSON相对于XML来讲,数据的体积小,传递的速度更快些
数据交互方面:JSON与js的交互更加方便,更容易解析处理,更好的数据交互
数据描述方面:JSON对数据的描述性比XML较差
传输速度方面:JSON的速度远远要快于XML
4.渐进增强和优雅降级
渐进增强:针对低版本的浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的体验效果
优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容
构建工具
1.webpack的理解,和gulp有什么不同?
webpack是模块打包工具,会分析模块间的依赖关系,然后使用Loaders处理他们,最后生成一个优化并且合并后的静态资源
gulp是前端自动化工具,能够优化前端工作流程,比如文件合并压缩
2.webpack打包速度很慢, 为什么?怎么解决?
模块太多
webpck可以配置externals来将依赖的库指向全局变量,从而不再打包这个库
3.对webpack的看法
webpack是一个模块打包工具,可以使用webpack管理你的模块依赖,并编译输出模块们所需要的静态文件。能很好的管理、打包web开发中所用到的HTML、js、css以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后生成了优化且合并后的静态资源。
webpack两大特色:
code splitting(可以自动完成)
loader 可以处理各种类型的静态文件,并且支持串联操作
webpack是以commonJS的形式来书写脚本,但是AMD/CMD的支持也很全面,方便旧项目进行代码迁移
webpck具有require和browserify的功能,但仍有很多自己的新特性:
对 CommonJS、AMD、ES6的语法做了兼容
对JS、css、图片等资源文件都支持打包
串联式模块化加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对conffeescript、ES6的支持
有独立的配置文件webpck.config.js
可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间
支持sourceUrls和sourceMaps,易于调试
具有强大的plugin接口,大多是内部插件,使用起来比较灵活
webpack使用异步IO并具有多级缓存,在增亮编译上更加快
网络&存储
1.http响应中content-type包含哪些内容?
请求中的消息主题是用何种方式解码
application/x-www-form-urlencoded
这是最常见的post提交数据的方式,按照key1=val1&key2=val2的方式进行编码
application/json
告诉服务器端消息主体是序列化后json字符串
2.get和post有什么不同?
get是从服务器上获取数据,post是像服务器传送数据
get请求可以将查询字符串参数追加到url的末尾;post请求英国把数据作为请求的主体提交
get请求数据有大小限制;post没有
post比get安全性更高
3.cookie和session有什么联系和区别?
cookie数据存放在客户的浏览器上,session数据放在服务器上
session比cookie更安全
单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie
一般用cookie来存储sessionid
4.多页面通信有哪些方案,各有什么不同?
localstroge在一个标签页里呗添加、修改、删除时,都会触发一个storage事件,通过另一个标签页里监听storage事件,即可得到localstorge存储的值,实现不同标签页之间的通信
settimeout+cookie
5.输入网站后到页面展现是过程?
通过dns解析获取ip
通过dns解析获取ip
tcp链接
客户端发送http请求
tcp传输报文
服务器处理请求返回http报文
6.客户端解析渲染页面
构建DOM树->构建渲染树->布局渲染树:计算盒模型位置和大小->绘制渲染树
7.前端性能优化
代码层面:避免使用css表达式,避免使用高级选择器,通配选择器
缓存利用:缓存ajax,使用CDN,使用外部js和css文件以便缓存
添加expires头,服务器配置Etag,减少DNS查找
请数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载
请求带宽:压缩文件,开始GZIP
代码层面的优化:
用hash-table来优化查找
少用全局变量
用innerHTML代替DOM操作,减少DOM操作次数,优化js性能
用setTimeout来避免页面是去响应
缓存DOM节点查找的结果
避免使用css Expression
避免全局查询
避免使用with(with会创建自己的作用域,会增加作用域链长度)
多少变量声明合并
避免图片和iframe等的空src,空src会重新加载当前页面,印象速度和效率
尽量避免写在HTML标签中写style属性
样式放在顶部,脚本放在底部
8.移动端性能优化
尽量使用css3动画,开启硬件加速
适当使用touch时间代替click时间
避免使用css3渐变阴影效果
可以用transform: translateZ(0) 来开启硬件加速
不滥用float。float在渲染时计算量比较大,尽量减少使用
不滥用web字体。web字体需要下载,解析,重绘当前页面
合理使用requestAnimationFrame动画代替setTimeout
css中的属性(css3 transitions、css3 3D transforms、opacity、webGL、video)会触发GUP渲染,耗电
9.分域名请求图片的原因和好处?
浏览器的并发请求数目限制是针对同一域名的,超过限制数目的请求会被阻塞
浏览器并发请求有个数限制,分域名可以同时并发请求大量图片
10.页面的加载顺醋
html顺序加载,其中js会阻塞后续dom和资源加载,css不会阻塞dom和资源的加载
浏览器会使用prefetch对引用的资源提前下载
没有defer或async,浏览器会立即加载并执行指定的脚本
有async,加载和渲染后续文档元素的过程将和script.js的加载与执行并行进行(下载一部,执行同步,加载完就执行)
有defer,加载后续文档元素的过程将和script.js的加载并行进行(异步),但是script.js的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成
11.计算机网络的分层概述
tcp/ip模型:从下往上分别是链路层,网络层,传输层,应用层
osi模型:从下往上分别是物理层,链路层,网络层,传输层,会话层,表示层,应用层
12.jscss缓存问题
浏览器缓存的意义在于提高了执行效率,但是也随之带来一些问题,导致修改了js、css,客户端不能更新
都加上了一个时间戳作为版本号
<script type="text/javascript" src="{js文件路径}?version=XXXXXX"></script>
13.说说tcp传输的三次握手 四次握手策略
三次握手:
为了准确无误地吧数据送达目标处,TCP协议采用了三次握手策略。用TCP协议把数据包送出去后,TCP不会对传送后的情况置之不理,他一定会向对方确认是否送达,握手过程中使用TCP的标志:SYN和ACK
发送端首先发送一个带SYN的标志的数据包给对方,接收端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息
最后,发送端再回传一个带ACK的标志的数据包,代表“握手”结束
如在握手过程中某个阶段莫明中断,TCP协议会再次以相同的顺序发送相同的数据包
断开一个TCP连接需要“四次握手”
第一次挥手:主动关闭方发送一个FIN,用来关注主动方到被动关闭方的数据传送,也即是主动关闭方告诫被动关闭方:我已经不会再给你发数据了(在FIN包之前发送的数据,如果没有收到对应的ACK确认报文,主动关闭方依然会重发这些数据)。但是,此时主动关闭方还可以接受数据
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号收到序号 +1(与SYN相同,一个 FIN占用一个序号)
第三次挥手:被动关闭方发送一个 FIN。用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会给你发送数据了
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次握手
14.TCP和UDP的区别?
TCP是基于连接的协议,也就是说,在正式收发数据前,必须和对方简历可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来
UDP是与TCP相应的协议。他是面向非连接的协议,他不与对方建立连接,而是直接就把数据包发送过去了
UDP适用于一次只传送少量数据,对可靠性要求不高的应用环境
15.HTTP和HTTPS
HTTP协议通常承载与 TCP协议之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS
默认HTTP的端口号为80,HTTPS的端口号为443
16.为什么HTTPS安全
因为网络请求需要中间有很多的服务器路由的转发,中间的节点都可能篡改信息,而如果使用HTTPS,密钥在你和终点站才有,https之所有说比http安全,是因为他利用ssl/tls协议传输。包含证书,流量转发,负载均衡,页面适配,浏览器适配,refer传递等,保障了传输过程的安全性
17.关于http 2.0
http/2 引入了“服务端推”的概念,它允许服务端在客户端需要数据之前就主动的将数据发送到客户端缓存中,从而提高性能
http/2提供更多的加密支持
http/2使用多路技术,允许多个消息在一个连接上同时交差
它增加了头压缩,因此即使非常小的请求,其请求和响应和header都只会占用小比例的带宽
18.defer 和 async
defer并行加载js文件,会按照页面上script标签的顺序执行
async并行加载js文件,下载完成立即执行,不会按照页面上script标签的顺序执行
19.Cookie的弊端
cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但是有很多局限性
第一:每个特定的域名下最多生成20个cookie
IE6或更低的版本,最多20个cookie
IE7和之后的版本最多50cookie
chrom和safari没有做硬性限制
第二:IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie
cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节
IE提供了一种存储可以持久化用户数据,叫做userdata,从IE5.0就开始支持。每个数据最多128K,每个月名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,就一直会在
优点:极高的扩展性和可用性
通过良好的编程,控制保存在cookie中的session对象的大小
通过加密性和安全传输技术(SSL),减少cookie被破解的可能性
只在cookie中存放不敏感数据,即使被盗也不会有重大损失
控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie
缺点:
cookie数量和长度的限制,每个domain最多只能有20调cookie,每个cookie的长度不超过4KB,否则会被截掉
安全性问题,如果cookie被人拦截了,那人就可以取得所有的session信息,即使加密也于事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就行
有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器保存一个计数器,如果我们把这个计数器保存在客户端,那么他起不到任何作用
20.浏览器本地存储
较高版本的刘拉你中,js提供了sessionStorage和globalStorage。在HTML5提供了localStorage来取代globalStorage
HTML5中的web storage包括了两种存储方式:sessionStorage和 localStorage
sessionStorage用于本地存储一个会话中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据随之销毁,因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储
而localStorage用于持久化的本地存储,除非主要删除数据,否则数据是永远不会过期的
21.web storage 和 cookie的区别
web storage的概念和cookie相似,区别是为更大容量存储设计的,cookie的大小是受限的,并且每次请求一个新的页面的时候cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用
除此之外,web storage拥有serItem,getItem,removeItem,clear等方法,cookie得自己封装setCookie,getCookie
但是cookie也是不可或缺的:cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而web stroage仅仅是为了在本地“存储”在存在
浏览器的支持除了IE7及以下不支持外,其他标准都会完全支持(ie及FF需要在web服务器里进行),值得一提的是IE总是办好事,例如IE7,IE6的userData其实就是js本地存储的解决方法,通过简单的代码封装就可以同意到所有的浏览器都支持web storage
localStorage和sessionStorage都具有相同的操作方法,例如setItem,getItem,removeItem等
22.cookie 和 session的区别
cookie数据存放在客户的浏览器上,session数据放在服务器上
cookie不是很安全,别人分析存放在本地的cookie进行cookie欺骗
考虑到安全应当使用session
session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用cookie
单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie
所以个人建议:
将登陆信息等重要信息放在session
其他信息如果需要保留,可以放在cookie
23.常见兼容性问题?
png24位的图片在ie6浏览器上出现背景,解决方案是做成png8,也可以引用一段脚本处理
浏览器默认的margin和padding不同,解决方案是加一个全局的*{margin: 0;padding:0;}来统一
IE6双边距BUG:块属性标签float后,又有横行的margin情况下,在ie6显示margin得比设置的大
浮动ie产生的双边距距离(IE6双边距问题:在IE6,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍)
.box{ float:left;
width:10px;
margin:0 0 0 100px;}
这种情况之下ie会产生20px的距离,解决方案是在float的标签样式控制中加入
_display:inline;将其转化为行内属性(_这个符号只有ie6识别)
渐进识别的方式,从总体中逐渐排除局部
首先,巧妙的使用“\9”这一标记,将ie浏览器从所有情况中分离出来
接着,再次使用“+”将IE8和IE7,IE6分离出来,这样IE8已经独立识别
.a{ background-color: #ccc;/*所有识别*/ .background-color: #ccc\9;/*IE6,7,8识别*/ +background-color: #ccc;/*IE6,7识别*/ _background-color: #ccc;/*IE6识别*/}
怪异模式问题:漏写DOCTYPE声明。firefox仍然会按照标准模式来解析网页,但是IE中会触发怪异模式,为了避免不必要的麻烦,最好声明<doctype html> 良好习惯
IE6浏览器常见的BUG
1.IE6不支持min-height,解决办法使用css hack
.target{ min-height: 100px; height: auto !important; height: 100px; //IE6下内容高度超过会自动扩展高度}
2.ol内的序号全为1,不递增。
为li设置样式display: list-item
3.未定位父元素overflow: auto;,包含position: relative;子元素,子元素高于父元素时会溢出
子元素去掉position: relative
不能为子元素取消定位时,父元素position:relative
4.IE6只支持a标签的:hover伪类
使用js为元素监听mouseenter,mouseleave事件,添加类实现效果
5.IE5-8不支持opacity,
.opacity{ opacity: 0.4; filter: alpha(opacity=60);/* for IE5-7 */ -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=60)";/* for IE 8*/}
6.IE6在设置height小于font-size时高度值为font-size
font-size:0;
7.IE6不支持PNG透明背景
IE6下使用gif图片
8.IE6-7不支持display: inline-block
设置inline并处罚hasLayout
display: inline-block;
*display: inline;
*zoom: 1;
9.IE6下浮动元素在浮动方向上与父元素便捷接触元素的外边距会加倍
使用padding控制边距
浮动元素display: inline;
10.通过块级元素设置宽度和左右margin为auto时,IE6不能实现水平居中
为父元素设置text-align: center
1,讲讲浅拷贝、深拷贝之间的区别
核心:引用类型和非引用类型的拷贝结果是不同的
浅拷贝只是拷贝基本类型的数据,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,因此存在父对象被篡改的可能,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存
//简单的浅拷贝vara =1;varb = a;//赋值console.log(b)//1a =2;//改变a的值console.log(b)//1
如果要实现深拷贝,用什么方法来实现
JSON.parse() + JSON.stringify()(缺点:只能处理可以被枚举的属性);
for in 循环递归遍历;
深拷贝就是能够实现真正意义上的数组和对象的拷贝。递归调用"浅拷贝"。(深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象)
如果你想要实现支持setter和getter特性的拷贝,该怎么实现?
Object.defineproperties (定义属性)、Object.getOwnPropertyDescriptors(es2017,获取对象的多个属性)、Object.getOwnPropertyDescriptor(老一点,获取对象的单个属性的属性),但babel可以解决。
2、原型链的prototype和__proto__的区别;
prototype 在 new 示例后会被转为 __proto__
__proto__是非标准化的;
所有东西的原型链向上延伸到原型链的顶端,是什么;
Object.prototype.__proto__,结果是null.
Function本身就是函数,Function.__proto__是标准的内置对象Function.prototype,Function.prototype.__proto__是标准的内置对象Object.prototype
3、如果想实现继承,说几种你知道的方法?
原型链继承、构造继承、实例继承、拷贝继承、组合继承、寄生组合继承
原型链继承
3、var、let、const的区别;
var 会变量提升;
let 声明的变量只在它所在的代码块有效;
const 声明后不能再修改其指向的目标,假如const 指向的是一个对象/数组,那么虽然不能更改指向目标,但是可以更改对象和数组内部的值;
进阶一:说到变量提升,class 声明一个类时,存在变量提升么?为什么?
不存在。因为要方便类的继承,先声明子类再声明父类;
进阶二:const 声明一个对象,如何让对象内部的属性的值也无法改变?
使用Object.freeze()锁死(es5新增特性);
对数组等引用类型的值,还是能修改的;
进阶三:全局作用域?函数作用域?块级作用域?作用域链?
js有哪些基本数据类型?
Boolean、Null、Undefined、Number、String、Object;
Symbol(es6新增)
进阶:es6新增的原型数据类型Symbol,特点是什么;
表示独一无二的值;
声明时不能使用new Symbol(),而是 Symbol();
声明时可以加参数,用于描述;
作为key时不能被遍历;
进阶2:如何声明两个相等的Symbol变量?
使用Symbol.for,参数相同时;
let a = Symbol.for('a');
let b = Symbol.for('a');
a === b; // true
####Promise是什么?* 是异步编程的一种解决方案;* 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。一般什么时候使用?* 处理异步请求时使用,比如ajax请求;有哪些状态?* 状态有pending、resolved、rejected;怎么捕获他的错误?* 最后写catch;* then里面第二个参数可以捕获;如果内部抛错,但是没有被捕获,这个没被捕获的错误接下来会发生什么事情?* 冒泡;能不能被trycatch捕获?为什么?* 不能,因为是异步编程。能不能被window.onerror捕获?* 不能newPromise((resolve,reject)=>thrownewError('a')).then(fn1).then(fn2,fn3).catch(fn4) 这个函数,会执行哪些函数* fn3,没了
4,从输入URL到浏览器显示页面发生了什么。(特别注意)
这题可以了解一下,尽管面试时候造飞船,真的干活可能还是拧螺丝。
1.在浏览器中输入url(解析IP地址)
2.应用层DNS解析域名
3.应用层客户端发送HTTP请求
4.传输层TCP传输报文(3次握手)
5.网络层IP协议查询MAC地址
6.数据到达数据链路层
7.服务器接收数据
8.服务器响应请求
9.服务器返回相应文件
二、页面渲染:现代浏览器渲染页面的过程是这样的:解析HTML以构建DOM树 –> 构建渲染树 –> 布局渲染树 –> 绘制渲染树。
在浏览器还没接收到完整的HTML文件时,它就开始渲染页面了,在遇到外部链入的脚本标签或样式标签或图片时,会再次发送HTTP请求重复上述的步骤。在收到CSS文件后会对已经渲染的页面重新渲染,加入它们应有的样式,图片文件加载完立刻显示在相应位置。在这一过程中可能会触发页面的重绘或重排。
5、async、await 的使用场景是什么?
连续的异步请求,下一步的异步请求依赖于前一步的异步请求结果;
进阶一:假如有A、B、C三个异步请求,异步请求C依赖于异步请求A和B的结果(即A和B完成后再发起C),那么你会如何实现它?
Promise.all();
设置状态分别标记A和B,A、B完成后会去修改自己的完成标记,然后检查所有的状态标记,假如都是完成状态,然后去执行异步请求C。
6、Promise是什么?
是异步编程的一种解决方案;
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
一般什么时候使用?
处理异步请求时使用,比如ajax请求;
有哪些状态?
状态有pending、resolved、rejected;
怎么捕获他的错误?
最后写catch;
then里面第二个参数可以捕获;
如果内部抛错,但是没有被捕获,这个没被捕获的错误接下来会发生什么事情?
冒泡;
能不能被try catch捕获?为什么?
不能,因为是异步编程。
能不能被window.onerror捕获?
不能
new Promise((resolve,reject)=>throw new Error('a')).then(fn1).then(fn2,fn3).catch(fn4) 这个函数,会执行哪些函数 * fn3,没了
7、数字计算:请问在js中,输入表达式 0.1 + 0.2 的结果是什么?
0.30000000000000004(能回答出来不是0.3,而是0.3后有若干个0和一个数字即可)
进阶一:为什么?
原因是浮点数和整数,在存储时的方法是不同的,因此相加的规则也是不同的;
进阶二:浮点数是怎么存储的(本问题比较难)(可以跳到进阶三,比本题简单)
而double类型就是双精度浮点数,这种指使用64位(8字节)来存储一个浮点数。根据规定,这64位bit里,分为三部分:第一部分(1bit):符号位,表示正负,正数为0,负数为1。第二部分(11bit):阶码位,也可以称为指数位。第三部分(52bit)尾数位,即表示实际数字的。假如正负符号的值为S,正数S为1,负数S为-1;假如指数位表示的值为E(计算后),指数位表示的值为2的E次方;假如尾数位表示的值为M,尾数位表示的值为M;根据科学表示法,任何一个范围内的浮点数可以通过以下方法来表示:(别问我为啥,我没去谷歌……)浮点数 = S * Math.pow(2,E) * M;
进阶三:我们在实际开发中,如果遇见了这种浮点数计算的情况,怎么处理比较合适?
8、移动端开发的时候,一般怎么实现自适应?
rem
vw和vh
媒体查询(bootstrap);
进阶一:他们的特点分别是什么?或者说实现原理是什么?
rem 根据 html 的 font-size;
vw是浏览器窗口宽度,vh是高度;
媒体查询是根据浏览器窗口宽度或高度,进行响应式选择显示哪个css;
进阶二:弹出输入框会发生定位错误,fixed布局,怎么解决?
9、在我们将开发好的页面,进入线上环境的时候,肯定要最大化性能优化,那么我们常见的做法有哪些?
https://csspod.com/frontend-performance-best-practices/
gzip、雪碧图、减少http请求数、减少DNS请求、避免重定向、缓存ajax请求、延迟加载、预加载、减少DOM数、使用框架例如React的虚拟DOM树、减少DOM操作、使用CDN、减少 css 里 @import 写法、
10、图片使用 雪碧图 和 base64字符串 你觉得哪个好?为什么?
雪碧图可以缓存;
base64可以减少请求数;
进阶一:如果你决定使用雪碧图/base64字符串,你会怎么做?
webpack 配 url-loader(base64);
webpack 的雪碧图插件 webpack-spritesmith;
1、说一下React
React是Facebook 开发的前端JavaScript库
V层:react并不是完整的MVC框架,而是MVC中的C层
虚拟DOM:react引入虚拟DOM,每当数据变化通过reactdiff运算,将上一次的虚拟DOM与本次渲染的DOM进行对比,仅仅只渲染更新的,有效减少了DOM操作
JSX语法:js+xml,是js的语法扩展,编译后转换成普通的js对象
组件化思想:将具有独立功能的UI模块封装为一个组件,而小的组件又可以通过不同的组合嵌套组成大的组件,最终完成整个项目的构建
单向数据流:指数据的流向只能由父级组件通过props讲数据传递给子组件,不能由子组件向父组件传递数据
要想实现数据的双向绑定只能由子组件接收父组件props传过来的方法去改变父组件数据,而不是直接将子组件数据传给父组件
生命周期:简单说一下生命周期:Mounting(挂载)、Updateing(更新)、Unmounting(卸载)
2、什么是JSX?为什么浏览器无法读取JSX
JSX 是JavaScript XML 的简写,是 React 使用的一种文件
它利用 JavaScript 的表现力和类似 HTML 的模板语法
使得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能
浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX
所以为了使浏览器能够读取 JSX,首先,需要用Babel转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器
3、React与Angular有何不同?
react是Facebook出品,angular是Google
react只有MVC中的C,angular是MVC
react使用虚拟DOM,angular使用真实DOM
react是单项数据绑定,angular是双向数据绑定
4、react生命周期函数
(1)Mounting挂载阶段
constructor()
componentWillMount()组件挂载到页面之前
render()创建虚拟DOM,进行diff运算,更新DOM树。不可进行setState()
componentDidMount()组件挂载到页面之后,可以在此请求数据
(2)Updateing更新阶段
componentWillReceiveProps()父级数据发生变化
shouldComponentUpdate()
性能优化:这个函数只返回true或false,表示接下来的组件是否需要更新(重新渲染)
返回true就是紧接着以下的生命周期函数,返回false表示组件不需要重新渲染,不再执行任何生命周期函数(包括render)
componentWillUpdate() 组件更新之前,不可进行setState() 会导致函数调用shouldComponentUpdate从而进入死循环
render()
componentDidUpdate()组件更新之后
(3)Unmounting卸载阶段
componentWillUnmount 组件卸载和销毁之前立刻停用
可以在此销毁定时器,取消网络请求,消除创建的相关DOM节点等
5、shouldComponentUpdate是做什么的,(react性能优化是哪个周期函数?)
shouldComponentUpdate 这个方法用来判断是否需要调用render方法重新绘制dom
因为DOM的描绘非常消耗性能,如果我们能在shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能
6、为什么虚拟 DOM 会提高性能? 说下他的原理
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能
Virtual DOM 工作过程有三个简单的步骤
1)每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲
2)然后计算之前 DOM 表示与新表示的之间的差异
3)完成计算后,将只用实际更改的内容更新 real DOM
7、调用setState之后发生了什么?
当调用setState后,新的 state 并没有马上生效渲染组件,而是,先看执行流中有没有在批量更新中
如果有,push到存入到dirtyeComponent中,如果没有,则遍历dirty中的component,调用updateComponent,进行state或props的更新
然后更新UI,react进行diff运算,与上一次的虚拟DOM相比较,进行有效的渲染更新组件
8、react diff 原理
diff(翻译差异):计算一棵树形结构转换成另一棵树形结构的最少操作
1)把树形结构按照层级分解,只比较同级元素
2)给列表结构的每个单元添加唯一的 key 属性,方便比较
3)React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
4)合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制
5)选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能
9、setState 何时同步何时异步?
1)setState 只在合成事件(react为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在jsx中常见的onClick、onChange这些都是合成事件)和钩子函数(生命周期)中是“异步”的,在原生事件和 setTimeout 中都是同步的
2)setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果
3)setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新
10、react渲染机制
1)当页面一打开,就会调用render构建一棵DOM树
2)当数据发生变化( state | props )时,就会再渲染出一棵DOM树
3)此时,进行diff运算,两棵DOM树进行差异化对比,找到更新的地方进行批量改动
11、React中refs 的作用是什么?
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄
我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄
该值会作为回调函数的第一个参数返回
12、组件的状态(state)和属性(props)之间有何不同
State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果
Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的
组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)
13、在构造函数中调用 super(props) 的目的是什么
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props
14、为什么在componentDidMount()中请求数据
componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以可以保证数据的加载
15、何为受控组件(controlled component)
在HTML 中,类似 , 和 <select> 这样的表单元素会维护自身的状态,并基于用户的输入来更新,当用户提交表单时,
前面提到的元素的值将随表单一起被发送,但在 React 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时
如 onChange 会更新 state,重新渲染组件,一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为”受控元素”
16、何为高阶组件(higher order component)
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象,最常见的可能是 Redux 的 connect 函数
除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为
如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC
17、React中的状态是什么?它是如何使用的?
状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props 不同,它们是可变的,并创建动态和交互式组件。可以通过 this.state() 访问它们
18、解释 React 中 render() 的目的
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示
如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 <form>、<group>、<div> 等
此函数必须保持纯净,即必须每次调用时都返回相同的结果
19、理解“在React中,一切都是组件”这句话
组件是 React 应用 UI 的构建块。这些组件将整个 UI 分成小的独立并可重用的部分
每个组件彼此独立,而不会影响 UI 的其余部分
20、react父子组件之间如何通信,兄弟组件呢?
父级传递子级:把数据挂载子组件的属性上,子组件通过this.props来接收父组件的数据
子级传递父级:父级需要定义一个修改数据的方法,把修改数据的方法传给子组件,当子组件需要修改父级数据时,调用父级传过来的修改方法
兄弟组件传递:属于同一个父级,父组件分别和这两个组件传递。比如子组件A操作执行父组件方法,父组件进行修改,然后把信息传给子组件B
21、请列举定义react组件的中方法
1)函数式定义的无状态组件
2)es5原生的方式 React.createClass方式
3)es6中extends React.Component定义的组件
22、react中component和pureComponent区别是什么?
PureComponent自带通过props和state的浅对比来实现 shouldComponentUpate(),而Component没有
比于Component,PureCompoent的性能表现将会更好
23、什么是无状态组件,与有状态组件的区别
无状态组件主要用来定义模板,接收来自父组件props传递过来的数据,使用{props.xxx}的表达式把props塞到模板里面
有状态组件主要用来定义交互逻辑和业务数据,使用{this.state.xxx}的表达式把业务数据挂载到容器组件的实例上(有状态组件也可以叫做容器组件,无状态组件也可以叫做展示组件),然后传递props到展示组件,展示组件接收到props,把props塞到模板里面
24、在哪些生命周期中可以修改组件的state
componentDidMount和componentDidUpdate
constructor、componentWillMount中setState会发生错误:setState只能在mounted或mounting组件中执行
componentWillUpdate中setState会导致死循环
25、调用render时,DOM一定会更新吗,为什么
不一定更新
React组件中存在两类DOM,render函数被调用后, React会根据props或者state重新创建一棵virtual DOM树,虽然每一次调用都重新创建,但因为创建是发生在内存中,所以很快不影响性能。而 virtual dom的更新并不意味着真实DOM的更新,React采用diff算法将virtual DOM和真实DOM进行比较,找出需要更新的最小的部分,这时Real DOM才可能发生修改
所以每次state的更改都会使得render函数被调用,但是页面DOM不一定发生修改
26、展示组件(Presentational component)和容器组件(Container component)之间有何不同
展示组件:展示专门通过props接受数据回调,并且几乎不会有自身的状态
容器组件:展示组件或者其他容器组件提供容器和行为;并调用actions,将其作为回调提供给展示组件,容器组件经常是有状态的
27、setState的两个参数
第一个参数是要改变的state对象
第二个参数是state导致的页面变化完成后的回调,等价于componentDidUpdate
28、React的生命周期函数中,当props改变时 会引发的后续变化,rander()函数什么时候执行
componentWillUpdate(){}之后
render
componentDidupdate(){}之前
29、React 和 Vue 相对于JQ在开发上有哪些优点?
虚拟DOM的优化,组件化利于维护,组件化方便复用
30、react-router的原理
BrowserRouter或hashRouter用来渲染Router所代表的组件
Route用来匹配组件路径并且筛选需要渲染的组件
Switch用来筛选需要渲染的唯一组件
Link直接渲染某个页面组件
Redirect类似于Link,在没有Route匹配成功时触发
31、为什么React Router v4中使用 switch 关键字 ?
虽然 <div> ** 用于封装 Router 中的多个路由
当你想要仅显示要在多个定义的路线中呈现的单个路线时,可以使用 “switch” 关键字,使用时,<switch>** 标记会按顺序将已定义的 URL
与已定义的路由进行匹配。找到第一个匹配项后,它将渲染指定的路径。从而绕过其它路线
32、了解redux么,说一下redux
redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer
三大原则:
1)唯一数据源(整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中)
2)reducer必须是纯函数(输入必须对应着唯一的输出)
3)State 是只读的, 想要更改必须经过派发action
redux的工作流程:
使用通过reducer创建出来的Store发起一个Action,reducer会执行相应的更新state的方法,当state更新之后,view会根据state做出相应的变化
1)提供getState()获取到state
2)通过dispatch(action)发起action更新state
3)通过subscribe()注册监听器
33、redux数据流通的过程
1)用户操作视图
2)发起一次dispatch。有异步:返回一个函数(使用thunk中间件),没有异步:return {}
3)进入reducer,通过对应的type去修改state,最后返回一个新的state
34、connect()前两个参数是什么?
mapStateToProps(state, ownProps)
允许我们将store中的数据作为props绑定到组件中,只要store更新了就会调用mapStateToProps方法,mapStateToProps返回的结果必须是object对象,该对象中的值将会更新到组件中
mapDispatchToProps(dispatch, [ownProps])
允许我们将action作为props绑定到组件中,如果不传这个参数redux会把dispatch作为属性注入给组件,可以手动当做store.dispatch使用
mapDispatchToProps希望你返回包含对应action的object对象
35、redux本身有什么不足?
1)向事件池中追加方法时,没有做去重处理
2)把绑定的方从在事件池中移除掉时,用的是arr.splice(index,1),这样可能会引起数组塌陷
3)reducer中state,每次返回都需要深克隆,可以在redux中获取状态信息时,深克隆,这样就不用在reducer里深克隆了
36、你怎么理解redux的state的
数据按照领域(Domain)分类,存储在不同的表中,不同的表中存储的列数据不能重复
表中每一列的数据都依赖于这张表的主键,表中除了主键以外的其他列,互相之间不能有直接依赖关系
把整个应用的状态按照领域(Domain)分成若干子State,子State之间不能保存重复的数据
State以键值对的结构存储数据,以记录的key/ID作为记录的索引,记录中的其他字段都依赖于索引
State中不能保存可以通过已有数据计算而来的数据,即State中的字段不互相依赖
37、React,redux可以运行在服务端吗?有什么优势
1)利于SEO
2)提高首屏渲染速度
3)同构直出,使用同一份JS代码实现,便于开发和维护
38、列出 Redux 的组件
1)Action – 这是一个用来描述发生了什么事情的对象
2)Reducer – 这是一个确定状态将如何变化的地方
3)Store – 整个程序的状态/对象树保存在Store中
4)View – 只显示 Store 提供的数据
39、解释 Reducer 的作用
Reducers 是纯函数,它规定应用程序的状态怎样因响应 ACTION 而改变。Reducers 通过接受先前的状态和 action 来工作,然后它返回一个新的状态。它根据操作的类型确定需要执行哪种更新,然后返回新的值。如果不需要完成任务,它会返回原来的状态
40、Store 在 Redux 中的意义是什么?
Store 是一个 JavaScript 对象,它可以保存程序的状态,并提供一些方法来访问状态、调度操作和注册侦听器。应用程序的整个状态/对象树保存在单一存储中。因此,Redux 非常简单且是可预测的。我们可以将中间件传递到 store 处理数据,并记录改变存储状态的各种操作。所有操作都通过 reducer 返回一个新状态