面试题 HTML CSS 面试题 1、如何理解HTML 语义化? 
让人更容易读懂(增加代码可读性)
 
让搜索引擎更容易读懂(SEO 搜索引擎优化)
 
 
2、默认情况下,哪些HTML 标签是块级元素、哪些是内联元素? 
3、盒子模型的宽度如何计算? 
4、argin 纵向重叠的问题 
5、margin 负值的问题 
对margin 的top left right bottom 设置负值,有何效果?
 
margin-top 和margin-left 负值,元素向上、向左移动
 
margin-right 负值,右侧元素左移,自身不受影响
 
margin-bottom 负值,下方元素上移,自身不受影响
 
 
6.float 布局 
如何实现圣杯布局和双飞翼布局? 手写clearfix
 
圣杯布局和双飞翼布局的目的:
三栏布局,中间一栏最先加载和渲染(内容最重要) 
两侧内容固定,中间内容随着宽度自适应 
一般用于PC网页 
 
圣杯布局例子:
三者都设置浮动且center宽度设置为百分百加上容器本身设置内边距
使得right的宽度无法在left的右侧排列被挤下来了
若要使得left移动至上图样式 设置margin-left:-100% ,设置这个实则就是父元素宽度的百分之百。也就是center(container)的宽度
(可以看成浮动元素它是别挤下来的 实际上是紧靠灰色部分的右侧。所以设置了这个就到了上图的位置) 
之后在设置相对定位 (right:200px即可)因为设置了相对定位是相对于自身移动,对其他元素没有影响。(可以看到定位的坐标为灰色的左上顶点处)
给margin-right设置负150即可成为下图
注意:不好理解!!! 就是给自身元素设置的margin-right:自身宽度。就会使自身宽度不占位置从而上移 
上述的布局就是圣杯布局  圣杯布局两边留白是通过padding设置的 而双飞翼布局是通过margin来进行两边留白的
 
双飞翼布局:
双飞翼布局是通过margin来进行两边留白。 
left直接设置margin-left:-100%即可。 
 
right:也设置margin-left:-190px。
1 2 3 4 5 6 7 手写clearfix  BFC解决清除浮动的问题 	.clearfix:after{         content:'' ;         display:table;         clear:both;     } 将clearfix属性添加到容器的class 内。 因为是浮动元素,高度塌陷了。为了防止不塌陷所以在container 内设置该样式 
 
7、flex 布局 
 flex 实现一个三点的色子
 
flex-direction :主轴方向(横向或者纵向) 
justify-content:主轴对齐方式(开始对齐,居中对齐,结束对齐) 
align-items:交叉轴的对齐方式(开始对齐,居中对齐,结束对齐) 
flex-wrap:换行 
align-self:子元素在交叉轴的对齐方式(开始对齐,居中对齐,结束对齐) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <style type="text/css" >     .box {         width: 200 px;         height: 200 px;         border: 2px solid #ccc;         border-radius: 10 px;         padding: 20 px;         display: flex;         justify-content: space-between;     }     .item {         display: block;         width: 40 px;         height: 40 px;         border-radius: 50 %;         background-color: #666;     }     .item:nth-child(2 ) {         align-self: center;      }     .item:nth-child(3 ) {         align-self: flex-end;     } </style>  body>     <div class="box">         <span class="item"></ span>        <span class  ="item" ></span>          <span class="item"></ span>    </div>  </ body>
 
8、absolute 和relative 分别依据什么定位? 
relative 依据自身定位
absolute 依据最近一层的定位元素定位(定位元素有:absolute relative fixed  body)
 
9、居中对齐有哪些实现方式? 
水平居中
垂直居中
 
1 2 3 4 5 6 7 8 9 水平居中:     inline 元素:text-align: center     block 元素:margin: auto     absolute 元素:left: 50 % + margin-left 负值 垂直居中: 	inline 元素:line-height的值等于height 值     absolute 元素:top: 50 % + margin-top 负值  **必须知道子元素的尺寸     absolute 元素:transform(-50 %, -50 %)    	absolute 元素:top, left, bottom, right = 0  + margin: auto 
 
10、CSS -图文样式 
line-height 如何继承
 
写具体数值,如30px ,则继承该值(比较好理解)
 
写比例,如2 / 1.5 ,则继承该比例(比较好理解)
直接比例乘以p标签的font-size 2*16=32px 
 
 
写百分比,如200% ,则继承计算出来的值(考点)
直接body里的font-size的比例乘200%就是20*2=40px 
 
 
 
11、CSS -响应式 
rem 是什么?
响应式布局的常见方案?
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 rem 是什么? 	rem 是一个长度单位     	px ,绝对长度单位,最常用         em ,相对长度单位,相对于父元素,不常用         rem ,相对长度单位,相对于根元素,常用于响应式布局           html {             font-size: 100 px;           } 		**任何使用长度的地方都可以用rem  例如宽度高度都可以 响应式布局的常见方案? 	media-query,根据不同的屏幕宽度设置根元素font-size  	body {             font-size: 0.16 rem;           } 	rem,基于根元素的相对单位 
 
JavaScript面试题 1、typeof 能判断的类型? 
考点:JS变量类型
 
2、何时使用===何时使用== 
考点:强制类型转换
 
3、window.onload和 DOMContentLoaded区别 
考点:页面加载过程,(页面渲染过程)
 
考点:JS作用域
 
5、手写节流throttle和防抖debounce 
考点:性能、体验优化
 
6、Promise解决什么问题? 
考点:JS异步 
 
7、值类型和引用类型的区别 
值类型各用各的,不会相互干扰。而引用类型一旦赋值了 b改变了 a也改变了
 
1 2 3 4 5 6 7 8 9 10 **值类型 let  a = 100 let  b = aa=200  log(b) **引用数据类型 let  a={age :20 }let  b=ab.age=21  log(a.age) 
 
8、typeof 运算符 
识别所有值类型
 
识别函数
 
判断是否是引用类型(不可再细分)
 
 
9、深拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 const  obj1 = {	age: 20 ,     name: 'xx×' ,     address: { 	city: 'beijing'  	}, 	arr:[ 'a' ,'b' , 'c' ] } const  obj2 = deepClone(obj1)  obj2.address.city = 'shanghai'  console .log(obj1.address.city) function  deepClone (obj={} ) {    if  (typeof  obj !== 'object' ||obj ==null ) { 	         return  obj                                       ***************** 	} 	     let  result 	if  (obj instanceof  Array ) {         result = [] 	}else  { 		result = {} 	}          for  ( let  key in  obj){       	     	if  (obj.hasOwnProperty(key)) {     	     		result[key] = deepclone(obj[key])     	}     }     return  result } ***let  result = { 	age: 20 ,     name: 'xx×' ,     address: { 		city: 'beijing'  	}, 	arr:[ 'a' ,'b' , 'c' ] }    
 
10、变量计算-类型转换 
let x1=obj1.x 是干扰人的
 
11、原型和原型链 1 2 3 4 5 6 7 8 **两种写的方式** console . log(`姓名${this .name}  ,学号${this .number}  ) console.log( '姓名'+ this.name + ',学号'+this.number ) 
 
class 
继承 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  People   {	constructor ( name) { 	this .name = name 	}	 	eat() { 	console . log(`$ithis.name} eat something` ) 	} 	} class  Student  extends  People   {	constructor (name, number) { 	super (name)  	this .number = number 	} 	sayHi(){ 	console .log(`姓名 ${this .name} 学号${this .number} ` )     } } const  xialuo = new  Student('夏洛' ,100 )log(xialuo.name) log(xialuo.number) xialuo.sayHi() xialuo.eat() 
 
1 2 1 、如何准确判断一个变量是不是数组?    a instanceof  Array  
 
12、作用域和闭包 1 2 3 1 、this 的不同应用场景,如何取值?2 、手写bind 函数3 、实际开发中闭包的应用场景,举例说明
 
作用域 
if for {} 就是块级作用域
 
自由变量 
闭包 
作用域应用的特殊情况,有两种表现:
答案为100
 
答案为100
 
闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找。不是在执行的地方!!! 
13、this 
应用场景
 
作为普通函数被调用  ->window 
使用call apply bind- >传入什么就是绑定什么 
作为对象方法被调用 ->返回对象本身 
在class方法中调用 ->当前实例本身 
箭头函数 ->上级作用域的this的值来决定 
 
注意:this取什么值,是在函数执行的时候确认的,不是在函数定义的时候确认的 
bind和call的区别是  bind会返回一个新的函数再去执行
 
this===window是因为function这个函数执行本身是setTimeout触发的执行,它并不是zhangsan.方法触发的执行。
 
特点:箭头函数本身没有this都是取它上级作用域的this
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 手写bind函数 由于fun1的隐式原型===Function 的显示原型 bind方法只有在Function .prototype function  fn1 (a,b,c ) {    log('this' ,this )     log(a,b,c)     return  'this is fn1'  } const  fn2 =fn1.bind({x :100 },10 ,20 ,30 )const  res = fn2()log(res) Function .prototype.bind1=function ( ) {         const  args = Array .prototypes.slice.call(arguments )          const  t =args.shift()          const  self = this        return  function ( ) {           return  self.apply(t,args)     } }     let  i a     for  (i = 0 ; i < 10 ; i++) {             a = document .createElement('a' )             a.innerHTML = i + '<br>'              a.addEventListener('click' , function  (e )  {                 e.preventDefault()                 alert(i)             })             document .body.appendChild(a)              } 如果是上述代码 无论点哪个标签都是显示10 ,因为此时i是全局作用域,只有当点击的时候才会去执行回调函数,而回调函数的alert(i)是一个自由变量所以会去全局找(循环都结束了),因为都是10   (js引擎在退出循环的时候,迭代变量i保存的是导致循环退出的值)     let  a     for  (let  i = 0 ; i < 10 ; i++) {             a = document .createElement('a' )             a.innerHTML = i + '<br>'              a.addEventListener('click' , function  (e )  {                 e.preventDefault()                 alert(i)             })             document .body.appendChild(a)              } 如果是上述代码就可以避免这个问题,因为此时i为块级作用域,(js引擎在后台会为每个迭代循环声明一个新的迭代变量),自由变量i就会在块中去找,因此就可以实现点击什么显示什么。 
 
14、异步和单线程 JS本质是单线程的。 也就是说,它并不能像JAVA语言那样,两个线程并发执行。但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢?
首先,JS的代码,大致分为两类,同步代码  和异步代码 。JS引擎的主线程负责执行代码,由于只有这一个线程,执行当然是同步的,即按照顺序来。另外,还有一个叫做任务队列  的东西,所有的异步代码都是从队列当中来。
所以实际上我们会发现,JS根本不可能同时执行两个任务,本质上还是单线程。
 因为这些任务的发生都不是在当下,而是过段时间以后再执行。因此时间不可控,你不能因为5秒后要执行一个函数,就让主线程闲置5秒什么都不干吧?所以你只能继续执行后续的同步代码。而当你单击鼠标或滚动窗口时,主线程可能正在执行其它代码,忙着呢!没工夫处理,因此,事件触发线程就负责来接收这个事件,并把要执行的任务暂时保存在任务队列当中。等主线程把手里的同步代码执行完,就立刻会向任务队列提取最新的任务。
 
单线程和异步 
遇到等待(网络请求,定时任务)不能卡住 
需要异步 
回调callback函数形式 
 
异步打印顺序100 300 200  异步不会阻塞 后面代码的执行300会立马出来。
同步 弹出200会卡主 不点确定300不会出来
 
基于JS是单线程语言 
异步不会阻塞代码执行 
同步会阻塞代码执行 
 
应用场景 
网络请求,如ajax图片加载 
定时任务,如setTimeout 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 手写Promise 加载一张图片 代码演示 const  url = 'http...' function  loadImg (src ) {    const  p =  new  Promise (       (resolve,reject)=>{         const  img = document .createElement('img' )         img.onload=() => {             resolve(img)         }         img.onerror=() => {             reject(new  Error (`图片加载失败${src} ` ))         }         img.src =src     }   )     return  p } loadImg(url).then(接收一个函数函数就是上面resolve里面的对象)                     	console .log(img.width) 	return  img }).then(img => {     console .log(img.height) }).catch(ex =>console .error(ex)) 情况2  如果有两张图 thenloadImg(url).then(img => { 	console .log(img.width) 	return  img    }).then(img => {     console .log(img.height)     return  loadImg(url2) }).then(img2 => {     console .log(img2.width)     return  img2 }) 这就是利用promise解决回调地狱的问题 
 
小结 
单线程和异步,异步和同步区别
基于JS是单线程语言 
异步不会阻塞代码执行 
同步会阻塞代码执行 
 
 
前端异步的应用场景:
 
Promise解决callback hell 
 
15、JS Web API(DOM) 
vue 和React框架应用广泛,封装了DOM操作 但DOM操作一直都会前端工程师的基础、必备知识 只会vue而不懂 DOM操作的前端程序员,不会长久 
不要被工具和框架限制了自己的能力
 
1 2 3 4 5 6 7 8 9 10 11 12 1 、DOM的本质是从HTML文件解译出的一棵树(一层一层)2 、DOM是哪种数据结构	是树(DOM树)结构 3 、DOM操作的常用API	* DOM节点的操作     * DOM结构操作     * attribute和property的操作 4 、attr和property 的区别	* property:修改对象属性,不会体现到 html结构中(尽量用这个) 	* attribute:修改html 属性,会改变html结构 	* 两者都有可能引起 DOM重新渲染 
 
property本身不是API的一部分,是一种JS属性操作的形式
 
设置attribute会将设置的属性嵌到dom结构里的(修改标签的属性)
 而property修改的是JS变量的一个属性(不会对标签产生任何的影响)
 
property和attribute 
property:修改对象属性,不会体现到 html结构中(尽量用这个) 
attribute:修改html 属性,会改变html结构 
两者都有可能引起 DOM重新渲染 
 
DOM结构操作 
新增/插入节点 
获取子元素列表,获取父元素 
删除子元素 
 
移动节点就是原本div1没有p2的 设置了此操作div1就有了p2
 
获取子元素列表有时候不是我们想要的 因为它会将文本元素一块打印出来
 
1 2 3 4 5 6 7 8 9 10 11 12 const  divchild = Array .prototype.slice.call(div1.childNodes).filter(child => {    if (child.nodeType===1 ){         return  true      }     	return  false  }) console .log('divchild' ,divchild)**filter():方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素;不会改变原始数组; return 后面判断结果,取布尔值,true 的话就添入新的filter数组中,false 的话,不会添进filter的数组中。**
 
DOM性能 
DOM操作非常“昂贵”,避免频繁的DOM操作(占用CPU多 ) 
对DOM查询做缓存 
将频繁操作改为一次性操作 
 
1 2 3 4 5 6 7 8 const  list = document .getElementById('list' )for (let  i=0 ;i<10 ;i++){    const  li = document .createElement('li' )     li.innerHTML = `LIST Item ${i} `      list.appendChild(li) } 这样就是频繁操作DOM,耗费性能 
 
16、BOM操作(Browser Object Model) 
17、事件 1 2 3 1 、编写一个通用的事件监听函数2 、描述事件冒泡的流程3 、无限下拉的图片列表,如何监听每个图片的点击?
 
事件绑定 
elem:绑定的按钮id 
 
事件冒泡 
stopPropagation组织冒泡 没有这个点击激活的时候由于会冒泡到body就会触发body从而打印取消 
事件代理(是基于事件冒泡来做的) 
绑定在父元素上 代码简介 (比每一个a标签都绑定一个元素)
减少浏览器的内存占用 (每一个a标签都去挂载事件监听,耗内存)
禁止滥用
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 function  bindEvent (elem,type,selector,fn ) {	if (fn == null ) {    		fn = selector     	selector = null  	} elem.addEventListener(type,event => {        	const  target = event.target 		if  (selector) {   		             if (target.matches(selector)){                  fn.call(target,event)             } 		}else  { 		             fn.call(target,event)         } 	}) } const  btn1 = document .getElementById('btn1' )bindEvent(btn1, 'click'  , event =>{ 	     event.preventDefault() 	alert(this .innerHTML) }) const  div3 = document .getElementById ('div3' )bindEvent(div3, 'click ' ,'a' , event =>{ 	event.preventDefault() 	alert(this .innerHTML) }) const  btn1 = document .getElementById('btn1' )bindEvent(btn1, 'click'  , function (event  ) { 	     event.preventDefault() 	alert(this .innerHTML) }) const  div3 = document .getElementById ('div3' )bindEvent(div3, 'click ' ,'a' , function (event ) { 	event.preventDefault() 	alert(this .innerHTML) }) 
 
下图就可以验证target.matches(selector) 其中代理绑定的是a标签不是button标签,因此就可以判断是否符合css选择器 
上述代码有错误,因为箭头函数没有this,会向上级作用域查找,为window,而window.innerHTML就不符合要求了
因此得将箭头函数转换为普通函数
 
描述事件冒泡的流程 
基于 DOM 树形结构 
事件会顺着触发元素向上冒泡 
应用场景:代理(是基于事件冒泡机制才能使用的) 
 
无限下拉图片列表,如何监听每个图片的点击 
事件代理 
用e.target获取触发元素 
用matches来判断是否是触发元素 
 
18、跨域 1 2 3 4  同源策略 **ajax请求时,浏览器要求当前网页和server 必须同源(安全) **同源︰协议、域名、端口,三者必须 前端:http: 
 
加载图片css js可无视同源策略 
1 2 3 4 5 6 1 、<img src=跨域的图片地址/>2 、<link href=跨域的css地址/>3 、<script src=跨域的js地址></script> 4、<img/ >可用于统计打点,可使用第三方统计服务5 、<link /> <script > 可使用CDN ,CDN一般都是外域6、<script>可实现JSONP 
 
跨域 
所有的跨域,都必须经过server端允许和配合 
未经server端允许就实现跨域,说明浏览器有漏洞,危险信号 
 
JSONP  访问https://imooc.com/,服务端定返回一个html文件吗? 
不一定,服务器可以任意动态拼接数据返回,只要符合html格式要求
 
1 2 3 4 1 、<script>可绕过跨域限制2 、服务器可以任意动态拼接数据返回3 、所以,<script>就可以获得跨域的数据,只要服务端愿意返回(跨域必须经过服务端的允许和配合,服务端如果愿意给你返回一个拼接好的数据的script的JSONP文件的话,这样就可以通过<script>可绕过跨域限制,从而获得跨域的数据) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function  ajax (url ) {	const  p = new  Promise ((resolve,reject ) => { 	const  xhr = new  XMLHttpRequest() 	xhr.open ( 'GET' , '/data/test.json'  , true )     xhr.onreadystatechange = function ( ) {         if  (xhr.readyState == 4 ){         	if  (xhr.status === 200 ){     			resolve(      				JSON . parse(xhr.responseText)     				)     			}else  if  (xhr.status===404 ){     				reject(new  Error (' 404 not found ' ))         	}    		 } 	 }         xhr.send(null )     }) return  p} const  url = '/data/test.json' ajax(url) .then(res  =>console .log(res)) .catch(err  =>console .error(err)) 
 
ajax知识点 
XMLHttpRequest 
状态码:readyState status 
跨域︰同源策略(如何绕过),JSON,CORS 
 
19、存储 1、描述cookie localStorage sessionStorage区别
容量 cookie 4kb  另外一个5M API 易用性 是否跟随http请求发送出去  
 
cookie 
本身用于浏览器和server通讯(本身是http请求的一部分)
 
被“借用”到本地存储来( localStorage sessionStorage这是html5之后才提出来的,所以之前都是拿cookie做本地存储)
 
可用document.cookie= ‘..’来修改(前端修改cookie的方式)=>赋值同名覆盖 不同名叠加
 
注意 :cookie的设计并不是用来本地存储,它是为了浏览器和客服端通讯,只是被借用到本地存储来
 
 
cookie的缺点 
存储大小,最大4KB(限制) 
http请求时需要发送到服务端,增加请求数据量 
只能用document.cookie = ‘.…’来修改,太过简陋 
 
localStorage和sessionStorage 
HTML5专门为存储而设计,最大可存5M(已经很大了) 
API简单易用 =>setItem getItem 
不会随着http请求被发送出去 
 
localStorage和 sessionStorage 
localStorage数据会永久存储,除非代码或手动删除 
sessionStorage 数据只存在于当前会话,浏览器关闭则清空 
一般用localStorage会更多一些 
 
20、防抖 防抖 debounce 
监听一个输入框的,文字变化后触发chaange事件 
直接用keyup 事件,则会频发触发change事件 
防抖∶用户输入结束或暂停时,才会触发change事件 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function  debounce (fn, delay = 500 ){ 	let timer = null                     	return function( ) {.		if  (timer) { 			clearTimeout(timer) 			} 		timer = setTimeout(() => { 			fn.apply(this , arguments )             timer = null  		}, delay)       } } input1.addEventListener('keyup' ,debounce(function ( ) { 	console .log (input1.value) }),600 ) 
 
对照下面这个
节流 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 节流throttle 1 、拖拽一个元素时,要随时拿到该元素被拖拽的位置2 、直接用drag事件,则会频发触发,很容易导致卡顿3 、节流:无论拖拽速度多快,都会每隔100 ms触发一次function  throttle (fn, delay = 100 ){ 	let timer = null                     	return function( ) {.		if  (timer) { 			return   			} 		timer = setTimeout(() => { 			fn.apply(this , arguments )             timer = null  		}, delay)       } } input1.addEventListener('drag' ,throttle(function (e ) {     		console .log (e.offsetX,e.offsetY) }),200 ) 
 
关于简历 
1 2 3 4 5 简洁明了,突出个人技能和项目经验(技术栈) 可以把个人博客,开源作品放在简历里 不要造假,保证能力上的真实性(斟酌用词,不要使用精通, 了解熟练即可) 谈谈自己的缺点 
 
React框架 1、事件 
bind this:修改方法的this指向。使用箭头函数this就指向当前实例,就不用bind(this)
 
关于event 参数
event. preventDefault()//阻止默认行为
 
event. stopPropagation() //阻止冒泡
 
event.target 指向当前元素,即当前元素触发
 
event.nativeEvent.target 指向当前元素 即当前元素触发
 
event.nativeEvent.currentTarget 绑定是绑定在document上** 
 
 
 
 
传递自定义参数 
 
2、setState 
不可变值(不能直接修改state)
concat,slice,filter 这些东西不会改变原来的list值。而push pop splice会改变不可用  
或者可以通过this.state.list.slice() 不传入值就相当于给list做了一个副本,这样就可以使用push,pop这种API,原本的list不变  
扩展对象可以用解构赋值 {…this.state.list,a:100} 
 
 
可能是异步更新
先打印再累加   想要获取最新的值就在setState传入第二个参数,第二个参数的值是一个函数
 
但是在setTimeout中setState是同步的  自己定义的DOM事件,setState是同步的 
标准写法应该这样
要销毁这个自定义的DOM事件
 
 
可能会被合并(仅限对象才会被合并,函数不会被合并)
 
 
3、组件生命周期  
4、高级特性 
函数组件
 
非受控组件
 建议写受控组件  因为受控没有ref  因为官网尽量不要写ref
 
 
Portals
Portals使用场景  overflow: hidden  父元素设置了BFC影响了子元素的展示,可以让子元素逃离父元素之外展示 父组件z-index值太小:同理 fixed需要放在body第一层级:同理
 
 
context
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 1 ) 创建Context容器对象:	const  XxxContext = React.createContext()   	 2 ) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:	<xxxContext.Provider value={数据}> 		子组件     </xxxContext.Provider>  		<Provider value={{username,age}}> 					<B/ >				</Provider>  这样包裹一下 B组件以及B的子组件都能用只不过需要声明接收       3) 后代组件读取数据: 	/ /第一种方式:仅适用于类组件  	  static contextType = xxxContext  / / 声明接收context 	  this.context / / 读取context中的value数据 	   	/ /第二种方式: 函数组件与类组件都可以  函数式没有this所以第一种不适合函数式组件 	  <xxxContext.Consumer> 	    { 	      value => ( / / value就是context中的value数据 	        要显示的内容 	      ) 	    } 	  </ xxxContext.Consumer>`` ` 在应用开发中一般不用context, 一般都它封装react插件 
 
 
异步组件
性能优化:异步组件—>组件比较大,路由需要懒加载
 lazyLoad  懒加载 路由组件最常用  就是避免100个组件去请求100次  最好的就是点哪个就请求哪个 
1 2 3 4 5 6 7 8 9 10 11 12 const  Login = lazy(() =>import ('@/pages/Login' ))  <Suspense fallback={<h1>loading.....</h1>}>      <Switch>         <Route path="/ xxx" component={Xxxx}/>         <Redirect to=" /login"/>     </Switch> </Suspense>  //这就是如果网络慢慢 迟迟不回来 要fallback指定一个组件component={Xxxx}显示 //Network选项卡 点谁加载谁  把网络故意调慢  点了About加载 会显示Loading //<h1>loading.....</h1>如果Loading要写成一个组件就另外写一个文件就可以 但是引入的时候不要懒加载 
 
 
性能组件(永远是面试的重点)
性能优化对于React更加重要
判断下一个状态的数据和前一个数据是否相同,不相同可以渲染,相同就不可以渲染。优化性能
背后的逻辑是什么? SCU默认会返回true,但是有返回false的权利
SCU一定要每次都用嘛?不一定,性能优化需要的时候用。需要的时候才优化
 
SCU使用总结** 
SCU 默认返回true ,即React默认重新渲染所有子组件
 
必须配合“不可变值”一起使用
 
可先不用SCU,有性能问题时再考虑使用
PureComponent 和memo 
 
PureComponent , SCU默认实现了浅比较
 
memo ,函数组件中的PureComponent
 
浅比较已使用大部分情况(尽量不要做深度比较)
 
 
immutable.js 
彻底拥抱“不可变质” 
基于共享数据(不是深拷贝),速度好 
有一定学习和迁移成本,按需使用 
 
 
高阶组件HOC
关于组件公共逻辑的抽离 
mixin , 已被React 弃用 
高阶组件HOC 
Render Props 
connect也是高阶组件 
 
接收一个组件,返回的是一个由函数拼接而成的组件
 
 
Render Props(比HOC更容易理解)
 
 
注意 :暴露的是什么,组件就传什么,比如下图,暴露的是APP 在入口文件APP相当于子组件所以直接在APP输入props即可
5、Redux 
redux怎么去获取异步action
单向数据流的图
 
6、React原理 函数式编程 
 
vdom和diff 
 
jsx本质 
1 2 3 4 5 6 7 8 9 1 、是一个 React.createElement 函数,他接收多个参数,执行返回vnode,vnode通过vdom的patch或者其他方法渲染页面2 、不是模板引擎,而是语法糖3 、第一个参数,可能是组件(大写),也可能是html 标签名(小写)4 、第二个参数是属性信息,如果没有属性则为 null ;第三个参数是子元素;     如果拥有多个子元素,可以依次放在第三个、第四个...     也可以用在数组中存放多个子元素	 4 、组件名,首字母必须大写( React规定)
 
合成事件 
1 2 3 4 5 6 7 1 、所有事件挂载到document  上2 、event 不是原生的,是 SyntheticEvent合成事件对象3 、和Vue 事件不同,和DOM事件也不同为何要合成事件机制? 1 、更好的兼容性和跨平台2 、载到document  ,减少内存消耗,避免频繁解绑3 、方便事件的统一管理(如事务机制)
 
setState 和 batchUpdata 
1 2 3 4 5 6 7 8 9 10 11 12 13 1 、setState无所谓异步还是同步2 、看是否能命中batchUpdate机制3 、判断isBatchingUpdates哪些能命中batchUpdate机制 1 、生命周期(和它调用的函数)2 、React 中注册的事件(和它调用的函数)3 、React可以“管理”的入口哪些不能命中batchUpdate机制 1 、setTimeout setInterval 等(和它调用的函数)2 、自定义的DOM事件(和它调用的函数)3 、React“管不到”的入口
 
Y就是异步的State N 就是同步的State
 
执行函数前处于batchUpdate 且isBatchingUpdates=ture。执行函数完之后isBatchingUpdates=false。
因为settimeout()这个函数式异步的就直接执行isBatchingUpdates=false。了 之后进行this.set的时候isBatchingUpdates已经是false了。所以判断setState是异步还是同步的时候,就看isBatchUpdates是true还是false 且设置这个是在入口中设置的。
 
组件之间如何通讯 
1 2 3 1 、父子组件props2 、自定义事件3 、Redux和Context
 
Context是什么,如何应用 
1 2 3 父组件,向其下所有子孙组件传递信息 如一些简单的公共信息,主题色,语言等。 复杂的公共信息,用redux 
 
shouldComponentUpdate用途 
 
两次异步操作合并成一次所以只加1,异步操作玩之后执行同步
 
纯函数 
1 2 3 返回一个新值,没有副作用(不会偷偷修改其他值) 重点:不可变值 如arr1=arr.slice() 
 
函数组件和class组件的区别 
1 2 3 纯函数,输入props,输出JSX 没有实例,没有生命周期,没有state 不能扩展其他方法 
 
什么是受控组件 
1 2 表单的值,收state 控制 需要自行监听onChange ,更新state 
 
何时使用异步组件 
 
多个组件有公共逻辑,如何抽离 
 
Redux如何进行异步请求 
 
PureComponent 有何区别 
1 2 3 实现了浅比较的shouldComponentUpdate 优化性能 但要结合不可变值使用 
 
React性能优化 
1 2 3 4 5 6 7 8 9 渲染列表时加key 自定义事件、DOM事件及时销毁 合理使用异步组件 减少函数bind this 的次数 合理使用SCU PureComponent和memo 合理使用Immutable.js webpack层面的优化(后面会讲) 前端通用的性能优化,如图片懒加载 使用SSR 
 
React和Vue的区别 
1 2 3 4 5 6 7 都支持组件化 都是数据驱动视图 都使用vdom 操作 DOM React使用JSX拥抱JS,Vue使用模板拥抱html React函数式编程,Vue声明式编程 React 更多需要自力更生,Vue把想要的都给你 
 
7、webpack webpack介绍 
1 2 3 4 5 6 7 8 9 10 webpack已经是前端打包构建的不二选择 每日必用,面试必考 成熟的工具,重点在于配置和使用,原理并不高优 前端代码为何要进行构建和打包 module  chunk bundle 分别什么意思,有何区别?loader和plugin的区别? webpack如何实现懒加载? webpack常见性能优化 babel-runtime和 babel-polyfill的区别 
 
webpack基本配置 
1 2 3 4 5 6 7 8 9 10 11 12 13 vue-cli create-react-app  **cli工程师 常用上述脚手架,而不会自己配置webpaclk ? 则面试不会通过 拆分配置和merge (公共的配置common 生产环境下的配置,开发环境下的配置) 跨域问题:开发环境下还会定义一个devserver 里可以通过设置代理proxy将本地/api/XXX代理到 localhost:3000 /api/xxx loader的执行顺序是从后往前 postcss-loader 浏览器的兼容性的 对css文件:先postcss-loader 浏览器的兼容性的一些东西做了再变成css插入到style中 对less文件,先通过less解析语法成css然后插入style中 图片大小小于5 kb用base64格式产出否则用file-loader的形式,产出url格式 
 
webpack高级配置 
1 2 3 4 5 基本配置只能做demo,不能做线上项目 多入口:entry要写两个。 output要通过[name]的变量去操作  plugins要:每一个入口都要创建一个新的HtmlWebpackPlugin的实例(new ) 	chunks:会帮你只引入什么名字的js文件 不写chunk会把html文件一块引入。 
 
抽离css文件 
1 2 3 开发环境下用的是通过css-loader转换成出css文件插入到style-loader里面去的 生成环境下需要用MiniCssExtractPlugin.loader,通过这种方式就不再是塞到style-loader里面去了 单独拧出来,(在plugins里面加了一个抽离css文件的plugins的配置)还是用new  MiniCssExtractPlugin标志一下抽离出的css文件是什么。抽离完还要压缩(optimization配置里面)抽离出来就可以在index.html引入抽离的css文件了 
 
抽离公共代码 
1 2 3 4 5 6 7 抽离公共部分相互引用,减少加载和执行的次数 开发环境下没必要做。 第三方模块复用一次的原因是是避免细微的改动重新加载这个模块,影响加载速度,耗费性能。 test 是模块来自  大小限制最好写3 kb 5 kB这样 name就是代码分割产出的chunk 多入口plugins里面引用new  HtmlWebpackPlugin下也要考虑代码分割的chunk 
 
懒加载 
1 2 引入动态数据->懒加载 异步代码也会产出一个chunk 文件名不是自己规定的 
 
moudle chunk bundle的区别 
1 2 3 4 5 module  -各个源码文件,webpack 中一切皆模块 只要是引入的就是模块chunk -多模块合并成的,如entry(一个入口就可以生成一个至多个chunk,因为入口定义的文件也包括其他文件一块引进来)          import () splitChunk 拆分代码也可以定义chunk 懒加载引入动态数据也是一个chunk         可以理解成内存中的一个概念,还没整理的输出 bundle -最终的输出文件(一个chunk对应一个bundle)bundle可能是很多个文件不止一个文件 
 
webpack性能优化 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 1 、优化打包构建速度-开发体验和效率    优化 babel-loader - 缓存 加一个cacheDirectory参数,加上之后只要ES6代码没有改,就不会重新编译,缓存一下。     				 - 有include和exclude两者选一个去明确打包范围 	 	happyPack -多进程打包工具 -JS单线程,开启多进程打包         					-提高构建速度(特别是多核CPU ) 							-把对.js文件的处理转交给id为babel的HappyPack实例 图3  	 	IgnorePlugin -避免引入无用模块 -例如moment.js这个日期处理的库 加载时间的库,200 多kb 就是因为把语言的库引进来了,可以通					 -过引入这个插件来避免引入这个模块,至于语言的模块就自己手动引入  -还能优化产出的体积  图1  	 	ParallelUglifyPlugin -开启多进程进行代码压缩JS JS单线程,开启多进程压缩更快和HappyPack原理类似 图四压缩就是直接输结果 						 	noParse  -避免重复打包  像一些min.js文件基本都是采用模块化处理过了,不用再重新打包 在moudule文件下加一下就好了如下图2  	     自动刷新 -一保存代码编译完之后浏览器自动刷新 开发环境用(devServer)默认开启会用      	热更新 -自动刷新的升级版,改完代码之后浏览器不要刷新,代码就生效,体验更好                         自动刷新:整个网页全部刷新,速度较慢                         自动刷新:整个网页全部刷新,状态会丢失 包括你点击的路由 自动刷新玩就会回到首页和你输入的状态下次就不见 						热更新:新代码生效,网页不刷新,状态不丢失                         引入插件,new 实例,devServer设置hot为true                          如果是改js文件的话就会导致自动刷新,原因是因为某些模块没有开启热更新的监听 图4                          自动刷新会影响你开发的体验再去开启热更新 	 	DllPlugin-针对大的库和大的第三方插件没必要每一次都把所有打包一遍,我们可以实现把第三方库打包好之后引用 *动态链接库插件 			 - 前端框架如vue React,体积大,构建慢 			 - 较稳定,不常升级版本 			 - 同一个版本只构建一次即可,不用每次都重新构建             webpack 已内置 DllPlugin支持             DllPlugin插件 -先把react进行预打包出dll文件(webpack.dull.js) 图5  产出两个文件 一个是加载了打包所有关于入口						  - react-react-dom的所有文件,另一个是索引             DlIReferencePlugin插件 -使用dll文件。使用就不要重新打包  			使用首先现在入口文件的index.html引入这个src = ‘./react.dull.js’这个文件 然后new 实例 图6  			 	webpack优化构建速度(可用于生产环境)					不可用生产环境         优化 babel-loader									 自动刷新         happyPack										  热更新         IgnorePlugin									  DllPlugin         ParallelUglifyPlugin  *必须用         noParse 	 	**总结**     IgnorePlugin直接不引入,代码中没有     noParse 引入,但不打包 	项目较大,打包较慢,开启多进程能提高速度 	项目较小,打包很快,开启多进程会降低速度(进程开销) 	按需使用      **ES6 Module和Commonjs区别**     ES6 Module静态引入,编译时引入  必须放在最上面 否则报错  图7   	Commonjs动态引入,执行时引入,有可能需要有可能不需要 (图7  里面的if 就不知道是否会被执行) 	只有ES6 Module 才能静态分析,实现Tree-Shaking(webpack打包的时候执行,打包的时候代码还没执行) 	webpack只是一个静态分析,静态构建,编译,代码还没正式在线上被用户去运行 2 、优化产出代码-产品性能  **更重要	体积更小     合理分包,不重复加载     速度更快,内存使用更少     ****每一个都是优化     小图片base64编码     bundle加hash(打包出的bunlde代码时加上hash)     懒加载     提前公共代码->做一个公共的包,不需要重复打包公共的模块     IgnorePlugin 还能优化产出的体积     使用CDN加速: 打包出的html 引入的文件前缀都加了cdn 图7  这仅仅是第一步还需要将打包的文件上传到cdn的网址     使用mode:production:去打包生成环境下的代码 自动开启代码压缩  Vue React 等会自动删掉调试代码(如开发环境的warning )     					自动开启Tree-shaking => 对未使用的代码删除 只要mode为production即可                          ES6 Module才能让tree-shaking生效commonjs就不行     Scope Hosting 将两个文件合并,多个函数放在一个函数里,使得作用域少 使得内存占用少一些,代码体积更小 图8  
 
babel 
1 2 3 4 5 6 7 8 9 10 11 12 13 前端开发环境必备工具 同webpack,需要了解基本的配置和使用 环境搭建&基本配置 	babel-demo npx babel src/index.js 这样就可以通过babel编译index,js文件     babel其实就是通过plugin将ES6语法转换为ES5 babel-polyfill(po里),core-js标准库集成了所有ES6 ES7新语法的polyfill的补丁(兼容性)但是这个库对ES6的generator函数(处理异步),被async /await 代替不支持, 但是regenerator这个库就支持了。 babel-polyfill就是这两个库的集合                         Babel 7.4 之后弃用babel                         推荐直接使用core-js和regenerator				 							问题:会污染全局环境   如果是自己独立开发可以用   babel-runtime:不会污染全局环境。产出第三方lib就要用这个,否则会污染全局环境 
 
8、 面试真题演练 1.前端为何要进行打包和构建 
1 2 3 4 5 6 7 8 代码层面     体积更小(Tree-Shaking、压缩、合并),加载更快     开发而言:编译高级语言或语法(TS,ES6+,模块化,scss )          兼容性和错误检查(Polyfill,postcss,eslint) 研发层面(前端工程化)     统一、高效的开发环境     统一的构建流程和产出标准     集成公司构建规范(提测、上线等) 
 
loader和plugin区别 
1 2 3 loader模块转换器,如less >css plugin扩展插件,如HtmlWebpackPlugin 常用的loader和plugin有什么? 之前讲过的能掌握即可 
 
babel和 webpack的区别 
1 2 babel - JS新语法编译工具,不关心模块化 webpack-打包构建工具,是多个loader、plugin 的集合 
 
如何产出一个lib 
1 参考webpack.dll.js里面有一个output.library 
 
webpack如何实现懒加载 
1 2 3 import 语法结合Vue React异步组件 结合React-router异步加载路由 
 
为何Proxy不能被Polyfill 
1 Proxy  的功能用 Object .defineProperty 无法模拟
 
组件和状态设计 
1 2 3 4 5 6 todoList: 1 、用数据描述内容2 、结构化3 、可扩展性4 、功能上拆分层次5 、容器组件(只管理数据)、UI(只显示视图)
 
9、项目流程 PM(项目管理)想在项目开发过程中增加需求,该怎么办 
1 2 3 不能拒绝,走需求变更流程即可 公司如果有规定,按规定走 否则,发起项目组和leader 的评审,重新评估排期 
 
项目即将延期了,该怎么办 
1 2 3 4 项目沟通 多人协作,沟通是最重要的事情 每日一沟通(如站会),有事说事,无事报平安 及时识别风险,及时汇报 
 
你将如何保证项目质量 
1 2 3 4 5 符合开发规范 写出开发文档 及时单元测试 Mock  API Code  Review  (让大佬帮你浏览一遍)