2023前端面试题

HTML+CSS

1 块元素垂直居中

1 弹性布局
display:flex;
justify-content: center;
align-items: center;

2 定位
position: absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%)


3. 定位
position:absolute;
left:0;right:0;
top:0;bottom:0;
margin:auto;

2 盒模型和怪异盒模型


普通盒模型     content + paddign*2 + border*2 + margin*2 = 普通盒模型
怪异盒模型     contnet + margin*2   = 怪异盒模型  

1.两者区别

标准盒模型总宽度 = width + 左右padding + 左右border + 左右margin

标准盒模型总高度 = height + 上下padding + 上下border + 上下margin

怪异盒模型总宽度 = width + 左右margin (width包含了padding和border)

怪异盒模型总高度 = height + 上下margin (height包含了padding和border)

注:当没有添加文档声明时,就会触发某些浏览器的怪异模式,如IE6

2.如何将标准盒模型转换为怪异盒模型

给给标准盒子加上这个属性:

语法:box-sizing:border-box;

注:box-sizing:content-box; 默认值

3 解决浮动塌陷


1 万能清除浮动 :after
2 overflow:hidden
3 给父元素添加高度
4 给父元素加边框
5 给父元素加padding
clear both
6 最后面添加有个空的div height:0 clear both


方法1: 给父元素加overflow:hidden;
方法2: 在浮动元素下面加空div,并添加样式
      div{
      clear:both;
      height:0;
      overflow:hidden;
      }
方法3: 万能清除浮动法:
  选择器:after{
          content: '';
          clear: both;
          display:block;
          height:0;
          visibility:hidden;
          overflow: hidden;
          }

BFC


块级格式化上下文,表示一块单独的渲染区
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,一个BFC中的元素都会垂直的沿着其父元素的边框排列。
清除浮动,
触发条件:
1.根元素html
2.float属性不为none
3.display为inline-block、table-cell、table-caption、flex、inline-flex
4.position为absolute或fixed
5.overflow不为visible

浏览器前缀


浏览器前缀是用来做兼容的
-ms- IE
-moz- 基于Gecko引擎的浏览器 比如 火狐
-o- 欧鹏
-webkit- chrom sfari

伪类和伪元素


伪类:获取不存在与DOM树中的信息。获取不能被常规CSS选择器获取的信息。
:active :link :foucs :hover :fist-chidren
伪元素:一般用两个冒号
:after :before :first-line
伪类和伪元素的区别?
伪类的操作对象是文档树中已有的元素,而伪元素则创建了一个文档树外的元素。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

4 em ,rem , px, vw,vh


1 em   根据父元素的倍数
2 rem 根据根元素的倍数(根元素的font-size的大小)     (适配会根据rem来设定) 动态设置 html的font-size
3 vw,vh   只适用于高版本浏览器 ie9以上   移动都可以用 【100%内核都是 -webkit-】
4 px像素
5 百分比   %


1 px就是像素,也是我们现在经常使用的基本单位,比如常常听到的电脑像素是1024x768的,表示的是水平方向是1024个像素点,垂直方向是768个像素点。
2 em参考物是父元素的font-size,默认字体大小是16px,所以1em不是固定值,因为它会继承父元素的字体大小
3 rem参考物是相对于根元素,我们在使用时可以在根元素设置一个参考值即可,相对于em使用,减少很大运算工作量,例:html大小为10px,12rem就是120px。
4 % 是相对于父元素的大小设定的比率。
5 vw是相对视口(viewport)的宽度而定的,长度等于视口宽度的1/100
假如浏览器的宽度为200px,那么1vw就等于2px(200px/100)
6 vh是相对视口(viewport)的高度而定的,长度等于视口高度的1/100
假如浏览器的高度为500px,那么1vh就等于5px(500px/100)

5 边框一像素问题


tarnsfrom : scale(0.7) 缩放   css3转换


解决问题:移动端1像素变粗
为什么移动端CSS里面写了1px,实际上看起来比1px粗;了解设备物理像素和逻辑像素的同学应该很容易理解,其实这两个px的含义其实是不一样的,UI设计师要求的1px是指设备的物理像素1px,而CSS里记录的像素是逻辑像素,它们之间存在一个比例关系,可以用javascript中的`window.devicePixelRatio`来获取,也可以用媒体查询的`-webkit-min-device-pixel-ratio`来获取。当然,比例多少与设备相关。在手机上border无法达到我们想要的效果。这是因为devicePixelRatio特性导致,iPhone的devicePixelRatio==2,而border-width: 1px描述的是设备独立像素,所以,border被放大到物理像素2px显示,在iPhone上就显得较粗。
解决方案:transform: scale(0.5) 方案,用高度1px的div充当边框
    div {
          height: 1px;
          background: #000;
          overflow: hidden;
      }
      /* 2倍屏 */
      @media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
          div {
              -webkit-transform: scaleY(0.5);
              transform: scaleY(0.5);
          }
      }
      /* 3倍屏 */
      @media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
          div {
              -webkit-transform: scaleY(0.33);
              transform: scaleY(0.33);
          }
      }

6 安卓和iOS兼容问题 ---- 前端显示的兼容问题


链接1   https://blog.csdn.net/Jkssns/article/details/103456913  
1、IOS下input默认样式(圆角、阴影).
解决方案
input {
-webkit-appearance: none;
border-radius: 0;
border: 1px #ccc solid;
}

2、在IOS下页面滑动卡顿,Android没问题
解决方案
body {-webkit-overflow-scrolling:touch; overflow-scrolling: touch;}

3、input type 改为button
解决方案
当input type为button,disabled为true,会出现背景色异常(其实就是禁用的样式)
把input的disabled改为readonly (只读)
opacity:1

4、input type=text切换到英文输入法IOS下的问题
解决方案
input添加autocapitalize属性 --- 自动大小写
<input class="SmallFour" type="text" autocapitalize="off" />

5、禁止数字自动识别为电话号码
这个比较有用,因为一串数字在iphone的部分浏览器上会显示成蓝色,样式加成别的颜色也是不生效的。不是我亲测,在微信内部浏览器没问题,但是在safari上有问题,IOS系统版本12.1.4
解决方案
在HTML的head里面配置 format-detection格式检验
<meta name="format-detection" content="telephone=no" />

6、input 的placeholder属性会使文本位置偏上
解决方案
line-height: (和input框的高度一样高)---pc端解决方法
line-height:normal ---移动端解决方法

-----------------------------------------------------------------------------------------------------------

7、input type=number之后,pc端出现上下箭头
解决方案
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}

8、是图片填充到外层的框内,很好用,直接给图片添加样式。
解决方案
object-fit: cover;
width:100%;
height:100%;

9、手机端按住不放 阻止浏览器默认响应事件 调试
解决方案
//clikMenu 你要点击的事件节点
function touchendmovie(clikMenu){
  var timeOutEvent = 0;
  $(document).on('touchstart',clikMenu,function(e){
      timeOutEvent = setTimeout(function(){
      //这里编写你要执行的事件 },300);
      //这里设置长按响应时间
      e.preventDefault();
  });
  $(document).on('touchmove',clikMenu,function(e){
      clearTimeout(timeOutEvent);
      timeOutEvent = 0;
  });
  $(document).on('touchend',clikMenu,function(e){
      e.stopPropagation();
      if(timeOutEvent != 0 ){
          console.log('这里是点击了一下');
      }
      clearTimeout(timeOutEvent);
  });
}

10、禁止复制、选中文本
解决方案
.el {
-webkit-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
  user-select: none;
}

7 css预处理器


1 sass less
 
scss 是sass的升级版
sass 不能直接被浏览器解析,需要编译成css才能用,其中提供了一些变量、循环等方法,类似于编程语言的特点,公司使用scss,有大括号,sass没有大括号,靠缩进

8 H5 新增新特性


1 新增语义化标签 nav , header ,footer ,section、aside、article
2 input 新增类型 email search url tel number date ···
3 视频video 音频audio
4 canvas新增 --- 画布
5 获取定位 谷歌浏览器不行()  
6 web存储   localStorage sessionStorage   (indexdb 本地数据库)
7 拖拽 ondrap


https://www.cnblogs.com/ainyi/p/9777841.html
H5 新特性
1. 语义化标签:header、footer、section、nav、aside、article
2. 增强型表单:input 的多个 type
3. 新增表单元素:datalist、keygen、output
4. 新增表单属性:placehoder、required、min 和 max
5. 音频视频:audio、video
6. canvas
7. 地理定位
8. 拖拽
9. 本地存储:localStorage - 没有时间限制的数据存储;sessionStorage - 针对一个 session 的数据存储,当用户关闭浏览器窗口后,数据会被删除
10. 新事件:onresize、ondrag、onscroll、onmousewheel、onerror、onplay、onpause
11. WebSocket:单个 TCP 连接上进行全双工通讯的协议

8.1 Cookies与localstorage、sessionStorage的区别


共同点:都是保存在浏览器端、且同源的
区别:
  一、cookie数据始终在同源的http请求中携带(即便不须要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,能够限制cookie只属于某个路径下 ,
  二、存储大小限制也不一样,cookie数据不能超过4K,同时由于每次http请求都会携带cookie、因此cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,sessionStorage能够达到5M,localStorage能改达到20M
  三、数据有效期不一样,sessionStorage:仅在当前浏览器窗口关闭以前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,所以用做持久数据;cookie:只在设置的cookie过时时间以前有效,即便窗口关闭或浏览器关闭
  四、做用域不一样,sessionStorage不在不一样的浏览器窗口中共享,即便是同一个页面;localstorage在全部同源窗口中都是共享的;cookie也是在全部同源窗口都是共享的

9 适配 *


rem来适配
1 后期字体大小不适配 就用px
2 rem插件    
由于rem是根据根元素的font-size大小而定,所以根据浏览器当前的分辨率改变font-size的值,就可以用rem作为统一单位适配移动端

第一种:
1.rem适配没问题
2.rem是根据根元素的大小(html的字体大小来计算)
3.html{ font-size:10} 1rem == 10px
4.根据移动设备的像素比 dpr ,再根据设备的宽度,按照某种算法 动态设置html 的 font-size,然后页面大小会随着font-size大小改变而改变,通过onsize 动态设置

第二种:
第4步:在媒体查询中@media-screen中,写了多个 根元素设置 html{font-size}

第三种:
我们公司移动端一般不太那么严格去适配,我们公司宽度都用百分比%,字体大小直接用px,高的话用padding,不会写死高度

第四种:
1 宽度都用百分比
2 高度还是用px
3 webpack vue react px2rem 直接能将你写的px转成rem

10 响应式布局


http://caibaojian.com/356.html
1 不同的终端显示不同的布局   media
2 不同分辨率显示布局一样 (视频)

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
(user-scalable = no 属性能够解决 iPad 切换横屏之后触摸才能回到具体尺寸的问题。 )

Media Queries 是响应式设计的核心。 它根据条件告诉浏览器如何为指定视图宽度渲染页面。假如一个终端的分辨率小于 980px,那么可以这样写:

@media screen and (max-width: 980px) {
#head { … }
#content { … }
#footer { … }
}

4. 设置多种试图宽度
假如我们要设定兼容 iPad 和 iPhone 的视图,那么可以这样设置:
/** iPad **/
@media only screen and (min-width: 768px) and (max-width: 1024px) {}
/** iPhone **/
@media only screen and (min-width: 320px) and (max-width: 767px) {}


@media screen and (max-width: 990px) and (min-width: 768px) {
  css样式
}

11 定位问题


relative
absolute
fiex
sticky
static

1 粘性定位
2 定位的时候 --- 如果父元素设置了transfrom,子元素的fixed定位会失效

12 iframe


嵌入页面来使用 <iframe src="www.baidu.com" ></iframe>
用来跨域 页面与页面之间的跨域访问

13,css优化性能


有了上面两个的基础我们再详细说下应该怎样来优化css提高性能



1,减少css嵌套,最好不要套三层以上,一般情况下块级元素加上类,里面的内联元素不用加,css写的时候块级class套内联tag,这样不仅可以减少css文件大小,还能减少性能浪费。

2,不要在ID选择器前面进行嵌套,ID本来就是唯一的而且人家权值那么大,前方嵌套完全是浪费性能。

3,建立公共样式类,把长段相同样式提取出来作为公共类使用,比如我们常用的清除浮动,单行超出显示省略号等等等,当然如果你使用sass,继承会让你更加方便,同时我是比较提倡使用sass的,之后肯定也会写一篇sass的博客。

4,缩写css,其中包括缩写maigin,padding,颜色值等等,要是有两个或者两个以上的margin-****,写成margin: * * * *有助于文件大小。

5,减少通配符*或者类似[hidden="true"]这类选择器的使用,挨个查找所有...这性能能好吗?当然重置样式这些必须的东西是不能少的。

6,有些人喜欢在类名前面加上标签名:p.ty_p 来进行更加精确的定位,但是这样往往效率更差,类名应该在全局范围除非公用是唯一的,所以这种做法是应该便面的。

7,巧妙运用css的继承机制,在css中很多属性是可以继承的比如颜色字体等等,父节点定义了,子节点就无需定义。

8,拆分出公共css文件,对于比较大的项目我们可以将大部分页面的公共结构的样式提取出来放到单独css文件里,这样一次下载后就放到缓存里,当然这种做法会增加请求,具体做法应以实际情况而定。

9,不用css表达式,可能大家接触比较少,但是要记住的是无论我们怎么炫酷,到了最后都是静态的,所以表达式只是让你的代码显得更加炫酷,但是他对性能的浪费可能是超乎你的想象的,因为它并不只是计算一次,一些小的事件可能都会增加它为了有效准确而进行计算求值的次数。

10,少用css rest,可能你会觉得重置样式是规范,但是其实其中有很多的操作是不必要不友好的,有需求有兴趣的朋友可以选择normolize.css

11,cssSprite,合成所有icon图片,用宽高加上bacgroud-position的背景图方式显现出我们要的icon图,这是一种十分实用的技巧,极大减少了http请求。
 

JavaScript

******1 javascript 数据类型


基本类型 String (显示) Number(运算) Boolean(判断) Undefined(声明未赋值) Null(对象的空) Symbol(做键值)
引用类型 Object Array Function

判断复杂数据类型   intanceof

区别
基本类型存在 栈中   用完就销毁   不能长存
引用类型     堆中   不会自动销毁

引用赋值和浅拷贝和深拷贝

引用赋值   就是 =   引用同一个地址 所有如果改变某个属性 所有引用都改变
浅拷贝   只拷贝一层   [...arr] {...obj}
深拷贝   遍历对象进行递归 , JSON.stringify + JSON.parse , immutable.js

遍历对象 1、 for(let key in obj){
            console.log(key + '---' + obj[key])
        }
        2、1)、Object.keys(obj)     数组的key值组成的数组
  2)、Object.values(obj)   数组的value值组成的数组

for...in和for...of区别


1.for...in 可以遍历对象
2.for...in 遍历数组得到数组的下标,for...of遍历的数组得到数组的元素

for in 和for of 区别

1、for...of无法遍历对象

2、for...in是遍历的索引,for...of遍历的是值

3、for...of支持类数组和字符串遍历且支持break,contain,return
 


 

forEach和map的区别


1.写法
2.返回值:
forEach()没有返回值,不可以链式调用,forEach()允许callback更改原始数组的元素
map()返回一个新数组,原数组不会改变。
3.没有办法终止或者跳出forEach()循环,除非抛出异常

 

2 深拷贝浅拷贝及引用赋值的区别


将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个对象,

3 排序

https://segmentfault.com/a/1190000016286789 sort排序 冒泡排序 选择排序

 

1.sort排序 按升序排列 arr.sort( function(n1,n2){ return n1-n2 }) 按降序排列 arr.sort( function(n1,n2){ return n2-n1 }) 2.冒泡排序 function bubbleSort(arr) { for (var i = 0; i < arr.length; i++) { for (var j = i + 1; j < arr.length; j++) { if (arr[j] < arr[i]) { [arr[j], arr[i]] = [arr[i], arr[j]] } } } } 3.选择排序 将最大或者最小的数放在最前面一个一个排 function selectSort(arr) { for (var i = 0; i < arr.length; i++) { var min = i for (var j = i + 1; j < arr.length; j++) { if (arr[min] > arr[j]) { min = j } } if (i != min) { [arr[min], arr[i]] = [arr[i], arr[min]] } } } 4.快速排序 function quickSort(arr){ qSort(0, arr.length - 1); return arr; function qSort(left, right){ if (left >= right)//两个数相遇则结束该轮排序 return; var key = arr[left];//取最左边的元素作为标识数 var i = left; var j = right; while (i != j){//两个数相遇则结束该轮排序 while (i != j && arr[j] >= key) j--;//j前移 [arr[j], arr[i]] = [arr[i], arr[j]]; while (i != j && arr[i] <= key) i++;//i后移 [arr[j], arr[i]] = [arr[i], arr[j]]; } qSort(left, j - 1);//对标识数前面的数继续该方法排序 qSort(j + 1, right);//对标识数后面的数继续该方法排序 } }

 

4 去重

https://www.cnblogs.com/lewiscutey/p/8269567.html

 

Set()方法去重(ES6新增) function unique(arr){ return [...(new Set(arr))]; } 第一种数组去重方法(使用Array.from): let arr = [12,43,23,43,68,12]; let item = new Set(arr); console.log(item);//结果输出的是一个对象 //使用Array.from转成数组 let arr = [12,43,23,43,68,12]; let item = Array.from(new Set(arr)); console.log(item);// [12, 43, 23, 68] 第二种数组去重方法(使用...扩展运算符): let arr = [12,43,23,43,68,12]; let item = [...new Set(arr)]; console.log(item);//[12, 43, 23, 68] indexOf 或者 include

 

5 闭包 **

闭包的作用是声明局部变量供外部使用,正常来讲,函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量,但是我们又需要使用函数内部的局部变量,所以就出现了闭包,函数套函数就可以称为一个简单的闭包。 1 声明局部变量供外部使用,防止变量污染全局 (如果不 return,你就无法使用这个闭包。把 return bar 改成 window.bar = bar 也是一样的,只要让外面可以访问到这个 bar 函数就行了。) 2 闭包因为有函数 所以会存在堆中 可以存储值 一般会用来做缓存 缺点 在IE中可能导致内存泄露 解决方案 手动清除,在退出函数之前,将不使用的局部变量全部删除(设置为null)。 3 写法 函数嵌套 内部函数会作为外部函数的返回值 内部函数因为作用域链可以访问外部函数的变量 会做为内部函数的返回值 代码 function fn1(){ var a = 10 return function(){ return a } }

 

闭包概念: 1. 有一个 A 函数,再 A 函数内部返回一个 B 函数 2. 再 A 函数外部有变量引用这个 B 函数 3. B 函数内部访问着 A 函数内部的私有变量 以上三个条件缺一不可 闭包特点: 1. 作用域空间不销毁 - 优点: 因为不销毁,变量页不会销毁,增加了变量的生命周期 - 缺点: 因为不销毁,会一直占用内存,多了以后就会导致内存溢出 2. 可以利用闭包访问再一个函数外部访问函数内部的变量 - 优点: 可以再函数外部访问内部数据 - 缺点: 必须要时刻保持引用,导致函数执行栈不被销毁 3. 保护私有变量 - 优点: 可以把一些变量放在函数里面,不会污染全局 - 缺点: 要利用闭包函数才能访问,不是很方便 代码: function fun() { var count = 1; return function () { count++ console.log(count) } } var fn = fun() fn() /* 2 */ fn() /* 3 */

 

6 面向对象 --- 封装

面向对象是一种编程思想 符合我们的生活逻辑 解 (面向过程) 答案 面向过程也是一种编程思想 数学逻辑的映射 解 第一步骤 第二步骤 第三步骤 结果

 

面向对象编程,使用构造函数构造对象 1. 先书写一个构造函数 2. 在构造函数内向对象添加一些成员 3.使用这个构造函数创造一个对象(和 new 连用) 4.构造函数可以创建对象,并且创建一个带有属性和方法的对象 5.面向对象就是要想办法找到一个有属性和方法的对象 6.面向对象就是我们自己制造构造函数的过程 代码: // 1. 先创造一个构造函数 function Person(name, gender) { this.age = 18 this.name = name this.gender = gender } // 2. 使用构造函数创建对象 var p1 = new Person('Jack', 'man') var p2 = new Person('Rose', 'woman') // 3. 使用原型向构造函数添加方法: Person.prototype.sayHi = function () { console.log('hello') } p1.sayHi() // 4. 实例化对象的 __proto__ 和所属的构造函数的 prototype 是一个对象空间 console.log(p1.__proto__ === Person.prototype) // true // 5. p1和p2都是Person的实例,p1.__proto__ 和 p2.__proto__ 指向的都是 Person.prototype,两个实例化对象p1和p2执行的是同一个方法。即构造函数原型Person.prototype里的方法。 console.log(p1.sayHi === p2.sayHi) // true

 

7 原型链

每一个对象都有原型对象 , 原型对象也有原型对象 ,依次向上,直到Object.prototype如果还没有最会指向null,这样形成一个线性的链就叫做原型链 原型链特点 原型链上的方法和属性 实例可以共享 共享的原因是什么? 实例会有指针 __proto__ 会指向 原型对象

 

原型链: 实例化对象的__proto__指向其构造函数的prototype,实例化对象的__proto__里面也有一个成员叫做constructor指向当前这个对象所属的构造函数。实例化对象的__proto__的__proto__指向顶级构造函数Object的prototype,实例化对象的__proto__的__proto__里面的constructor指向顶级构造函数Object。Object.prototype就到顶了,Object.prototype 的 __proto__ 就是 null。 原型链的访问原则 访问一个对象的成员的时候,自己没有就会去 __proto__ 中找,如果 __proto__ 里面没有就再去 __proto__ 里面找,一直找到 Object.prototype 里面都没有,那么就会返回 undefiend。

 

8 继承 说话的继承都是为了优化代码,优化性

组合继承 = 借用构造函数继承 + 原型对象继承 多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只需要继承那个类即可。 多个类可以称为子类,单独这个类称为父类或者超类,基类等。 子类可以直接访问父类中的非私有的属性和行为。 几种继承方式: 1.通过extends关键字让类与类之间产生继承关系。 例如: class B extedns A { } 2.原型链继承 3.构造函数继承 4.组合继承 5.原型式继承(使用Object.create()方法) 二、继承的好处? 1、提高了代码的复用性。 2、继承的出现让类与类之间产生了关系,提供了多态的前提。 //超类 父类 假继承 function A(name, age) { this.name = name; this.age = age; } A.prototype.eat = function () { console.log(this.name + "吃 " + this.name); }; Dog.prototype = new A(); Cat.prototype = new A(); function Dog(name, age) { A.call(this, name, age); } function Cat(name, age) { A.call(this, name, age); } var dog1 = new Dog("小白", 3); var dog2 = new Dog("小白1", 31); var cat1 = new Cat("喵咪", 3); console.log(dog1, cat1); dog1.eat(); cat1.eat(); console.log(dog1.eat === dog2.eat); //true

 

1.组合继承 function Person() { this.name = 'Jack' } Person.prototype.sayHi = function () { console.log('hello') } function Student() { Person.call(this) } Student.prototype = new Person() var s1 = new Student() 2.ES6类class的继承 function Person() { this.name = 'Jack' } Person.prototype.sayHi = function () { console.log('hello') } // 下面表示创造一个 Student 类,继承自 Person 类 class Student extends Person { constructor() { // 必须在 constructor 里面执行一下 super() 完成继承 super() } } var s1 = new Student() 3 属性继承 -- 只继承属性不继承方法 4 原型继承 -- 把自己完全变成父亲

 

9 this的指向

普通函数的this 谁调用指向谁 把谁找到 就看.前面的对象 全局window可以省略的 箭头函数的this会指向上层环境 不会改变 箭头函数不能做构造函数,因为他的this指向不变 没有arguments 对象 组件内部生命函数 一定要 箭头函数 this会指向当前组件 add=()=>{ this.指向当前组件 } 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系 1.全局定义的函数直接调用,this => window 2.对象内部的方法调用,this => 调用者 3.定时器的处理函数,this => window 4.事件处理函数,this => 事件源 5.自调用函数,this => window 6.call 和 apply 和 bind强行改变this指向 函数名.call(要改变的this 指向,要给函数传递的参数1,要给函数传递的参数2, ...) 函数名.apply(要改变的this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...]) bind方法不会立即执行函数,而是返回一个已经改变了 this 指向的函数 --- bind 返回的是函数 var newFn = 函数名.bind(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...); newFn(传递参数) this指向它调用的对象 指向window--- 普通函数调用的时候 定时器 forEach 事件绑定IE 指向上一层函数--- 箭头函数指向创建环境 指向自己--- 自定义构造函数 事件函数 对象

 

10 事件机制 -- eventLoop 宏任务

微任务

Js是单线程的, 代码分为同步代码和异步代码, 代码执行时, 同步的进入主线程, 将异步代码放在WEB API中, 等达到指定条件, 再放入任务队列中. 主线程内的任务执行完毕为空,会去任务队列读取对应的函数,进入主线程执行 宏任务 普通那些 微任务 * .then() * .catch() * .progress() * $nextTick(()=>{//dom渲染完成之后执行}) 异步队列 setTimeout() setInterval() ajax() 绝对重点 --- 笔试题 setTimeout(() => { console.log("a",5) //5 Promise.resolve().then(()=>{ console.log("b",6) //6 }) setTimeout(()=>{ console.log("zzz",8) //8 }) }) console.log("c",1) // 1 Promise.resolve( console.log("d",2) ).then(() => { console.log("r",4) // 4 }) setTimeout(() => { console.log("F",7) //7 }) console.log("g",3) //3

 

11 判断是否是数组类型等等

typeof 判断基本类型 typeof n 数子 'number' typeof false 'boolean' 所有的引用类型 用 typeof 都返回 'object' 如果判断引用类型 instanceof 实例与构造函数之间关系 arr instancof Array fn instanceof Function obj instanceof Object Array.isArray(arr) 2.instanceof instanceof用来判断A是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。instanceof检测的是原型,内部机制是通过判断对象的原型链中是否有类型的原型。 {} instanceof Object; //true [] instanceof Array; //true [] instanceof Object; //true "123" instanceof String; //false new String(123) instanceof String; //true

 

12 改变this指向

call(指向对象,参数1,参数2) apply(指向对象,集合形式的参数) bind(指向对象,参数1,参数2) bind需要再调用

 

13 重排和重绘

发生在数据渲染 的时候 结构发生改变 重排 不影响布局叫重绘 dom删除增加 dom宽高改变 (布局变了) css变了叫做重绘 display:block dsplay:none (重绘) 重排一定会触发重绘 而重绘不一定会触发重排 一、 CSS中避免回流、重绘 尽可能在DOM树的最末端改变class 避免设置多层内联样式 动画效果应用到position属性为absolute或fixed的元素上 避免使用table布局 使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘 二、 JS操作避免回流、重 避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称 避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中 先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘 避免循环读取offsetLeft等属性,在循环之前把它们存起来 对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流

 

14 解析地址

http://www.baidu.com/#/list?name=sss&zzz=fff query 问号后面 hash # list

 

15 地址栏输入地址都做什么了

1 缓存里面去找路径 有的话直接就返回了 没有 才有下一步 2 向后端发请求 三次握手 四次挥手 3 返回资源 浏览器解析 4 重排和重绘 5 记录在dns缓存了 第一次握手:客户端要和服务端进行通信,首先要告知服务端一声,遂发出一个SYN=1的连接请求信号,“服务端哥哥,我想给你说说话”。 第二次握手:当服务端接收到客户端的连接请求,此时要给客户端一个确认信息,“我知道了(ACK),我这边已经准备好了,你现在能连吗(SYN)”。 第三次握手:当客户端收到了服务端的确认连接信息后,要礼貌的告知一下服务端,“好的,咱们开始联通吧(ACK)”。 第一次挥手:双方交流的差不多了,此时客户端也已经结尾了,接下来要断开通信连接,所以告诉服务端“我说完了(FIN)”,此时自身形成等待结束连接的状态。 第二次挥手:服务端知道客户端已经没话说了,服务端此时还有两句心里话要给客户端说,“我知道你说完了(ACK),我再给你说两句,&*……%¥”。 第三次挥手:此时客户端洗耳恭听继续处于等待结束的状态,服务器端也说完了,自身此时处于等待关闭连接的状态,并对告诉客户端,“我说完了,咱们断了吧(FIN)”。 第四次挥手:客户端收知道服务端也说完了,也要告诉服务端一声(ACK),因为连接和断开要双方都按下关闭操作才能断开,客户端同时又为自己定义一个定时器,因为不知道刚才说的这句话能不能准确到达服务端(网络不稳定或者其他因素引起的网络原因),默认时间定为两个通信的最大时间之和,超出这个时间就默认服务器端已经接收到了自己的确认信息,此时客户端就关闭自身连接,服务器端一旦接收到客户端发来的确定通知就立刻关闭服务器端的连接。 到此为止双方整个通信过程就此终结。这里要声明一下:断开链接不一定就是客户端,谁都可以先发起断开指令,另外客户端和服务端是没有固定标准的,谁先发起请求谁就是客户端。 问题: 1.为什么断开链接的时候客户端设置的定时器时间等待要2MSL(两个通信报文的最大时间)? 这个问题也很好理解,当客户端最终告诉服务器端断开确认的时候,他不知道自己的发出的指令是否能准确的一次性被服务器接收。假如服务器没有接收到(这已经耗费了一个报文的最大通信时间了),服务器端将会重新发起一个结束通话的指令(FIN)到客户端,客户端又接收到了服务器发来的结束通信指令将继续给服务器进行一个确认,有人会说那要是客户端发出的确认信息服务端没收到,而服务端重发的断开指令客户端也没收到怎么办,说实话我也无奈,遇到这种情况咱们干脆认为网确实不行了。 2.为什么建立连接要三次握手而断开连接要四次挥手? 说起这个,打一个比喻,目前祖国正在高速发展高铁,建立连接的过程正如上海到北京打通一条高铁线,TCP通信过程是一个全双工模式,即在这条高铁线上要有两个轨道,即能从上海发车到北京又能从北京发车到上海,甚至两边可以同时发车。所以断开连接前提就是要保证两条轨道都没有车,然后双方才能各自发起断开动作。 双方各自工作流程图: 客户端工作流程: 注意:在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。 服务器端工作流程:

 

16 http 面试

1、http协议:是超文本传输协议,信息是明文传输。如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息。 2、https协议:是具有安全性的ssl加密传输协议,为浏览器和服务器之间的通信加密,确保数据传输的安全。 (1)申请方式不一致;(2)传输协议不一致;(3)端口不一致;(4)安全性不一致 http特点 (1)支持客户端/服务器模式 HTTP工作于客户端服务端的架构之上,浏览器作为客户端通过url向服务器及web服务器发送请求, web服务器根据接收到的请求向客户端发送响应信息。 (2)简单快速 客户端向服务器请求时,只需传送请求方法和路径,请求方法有post、get等,每种方法规定了客户端与服务端 连接的类型不同。由于HTTP协议简单,使得HTTP服务程序规模小而且通信速度很快。 (3)灵活 HTTP允许传输任意类型的数据对象。 (4)无连接 限制每次连接只能处理一个请求,服务器处理完客户端的请求并收到客户端的应答后即断开连接, 采用这种方式可以节省时间。HTTP1.1后默认采用keepline长连接,服务器要等一段时间后才能断开连接, 以保证连接特性。但是你始终都要认为HTTP请求在结束后连接就会关闭,这是HTTP的特性。 与下层实现在结束后是否关闭连接都不会改变这个特性,长连接可以理解为下层实现对上层透明。 (5)无状态 无状态是指协议对事务处理没有记忆能力,意味着如果后续处理需要前面的信息,则必须被重传, 这可能导致每次连接的数据量增大,另一方面不需要前面信息时,它的应答就较快。 http 请求方式 get post delete .... http 状态 100 请求继续 200 成功 301 (重定向) 401 (参数错误) 404 (url错了) 500 (服务器代码错了) 请求头特别重要 content-type 特别重要 // 面试--重点题 post请求 axios 默认请求 content-type:application/json 如果要是跨域 通过 webapck 代理 解决跨域 proxy:{} //

 

17,继承的方式有那几种?

继承的方式有那几种? 1、原型链继承 父类的实例作为子类的原型 /2、借用构造函数继承(伪造对象、经典继承) 复制父类的实例属性给子类 3、实例继承(原型式继承) 4、组合式继承 调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用 5、寄生组合继承 通过寄生的方式来修复组合式继承的不足,完美的实现继承 6、es6 extends继承 代码量少,易懂 ES5继承和ES6继承的区别 es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中 Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this) es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this ----------------------------- 4、面向对象的继承方式有哪些? 原型链继承 构造继承 实例继承 拷贝继承 支持多继承 组合继承 寄生组合继承

 

18、浅拷贝深拷贝

深浅拷贝都是针对引用类型而言的,浅拷贝只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。 浅拷贝 就是指向对象的指针,意思就是拷贝出来的目标对象的指针和源对象的指针,指向的是同一个空间(改变拷贝出来的对象,源对象也会改变) 深拷贝 指的是拷贝对象的具体内容,拷贝结束收,内存中的值是完全相同的,但是内存地址不一样,两个对象之间互不影响(就是不回改变源对象) 为什么要用深拷贝: 列如把一个数组,对象a赋值给另一个变量b,当b改变的时候,a中对应的值不发生变化。 使用递归: 使用JSON: 不足:1,无法拷贝对象中的方法属性 2,无法拷贝 对象中值为undefined的属性 setTimeout(表达式,延时时间):   在执行时,是在载入执行一次后延迟指定时间后,再执行一次表达式,需要函数触发;被动触发 setInterval(表达式,交互时间):   它从载入后,立即进入计算状态,每隔指定的时间就执行一次表达式;主动触发

 

19 阻止冒泡相关的三种方式 事件委托

1.event.stopPropagation(); 事件处理过程中,阻止了事件冒泡,但不会阻击默认行为 2.return false; 事件处理过程中,阻止了事件冒泡,也阻止了默认行为 还有一种有冒泡有关的: 3.event.preventDefault(); 它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为 事件委托也称为事件代理。就是利用事件冒泡,把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托就无法实现。 比如,我们现在有一个无序列表,在无序列表里面有五个li,我们想要给每个li添加一个点击事件,这个时候,我们常规操作是通过循环给每个li添加点击事件。 我们就可以用到事件委托,即给ul注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器。 <script> var ul = document.querySelector('ul'); ul.addEventListener('click',function(e){ e.target.style.color = 'orange'; }) </script> 比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢? 操作DOM次数过多,造成浏览器的重排和重绘就越多; 每个事件都是一个对象,事件处理程序越多,占用的内存越多,影响前端性能; 添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能

 

20、 数组的一些方法

1 splice 切 一个参数 : 从开始切到结束 二个参数: 从开始位置切几个 三个参数:从开始位置切几个,添加、、、 slice是指定在一个数组中的元素创建一个新的数组,即原数组不会变 2、slice 复制 一个参数:从开始位置到结束 二个参数:从开始位置到结束位置 它能够实现对数组元素的删除、插入、替换操作,返回值为被操作的值,即原数组被改变。 3、reverse 翻转数组,返回值为改变后的数组 4、concant 拼接数组 返回值为拼接后的数组 5、unshift: 在数组前面添加,返回值为改变以后的长度 6、push 在后面添加,返回值为改变后的数组长度 7、pop 删除最后面一个 返回值为被删掉的那个值

 

11 ES6

1 箭头函数 ()=> this指向 固话不变 (原生js里面使用不是特别多 ) vue - react 2 Promise async await 由于 js异步代码 --- 不是谁先调用谁完成 Prmose.relove() .then() .then() .then().catch(err=>) Promise.reject().catch() Promise.all() // Promise.race() 只要有一个完成就执行 Promise.all([fn1,fn2,fn3,fn4]).then(res=>[]) --- ***** 都完成之后调用 5接口 返回数据 async function del(){ awiat fn1() await fn2() .. } del().then() 3 await 不能单独使用 4 解构赋值 let [] = [a,b] a=10 b=11 let [b,a] = [a,b] let {name,age} = {name:"zzzz",age:20} 5 ... 浅拷贝 [...arr] {...obj} 深拷贝 ... 模拟arguments 获取实参的集合 箭头没有arguments对象 6 `` 模板字符串 ${} 7 Set 能去重复 保证数据唯一 [...new Set(arr)] --- 8 对象简写 新增的对象方法 Object.assign({},obj1,obj2) //合并对象 {...} Object.frzze() 创建不可更改的对象 Object.definedProperty() ****** vue 双向数据绑定原理 2.0 ---- 3XXX使用的不是这个 Proxy (代理不是一会儿) 利用 原生 Object.defineProperty 这个方法来监听和改变值的, defineProperty 有两个函数 一个set,一个是get get函数 使用数据就触发 -- 调用数据的时候触发 get方法来进行同步数据 set函数 修改数据的时候触发 渲染视图的方法 render() 9 symbol 唯一 为了给对象添加key值来使用 10 class 必会 继承 原型对象 11 数组的方法 include 是否包含 find((item) //返回是元素 findIndex((item)) //返回值下标 es5遍历 filter map every some redcuer((第一个参数,后面的每一个参数)=>) //请和 12 let const 都不能重复生命 const不能重新赋值 let可以重新赋值 没有预解析 先声明再调用 块级作用域 {} 外部访问不到 不用怕变量污染全局,也不怕快里面重复生命

 

ES6

1 promise

1 解决异步回调问题 2 因为 我们开发程序 有可能是有关联的 例如 可以程序 有三步组成 第一步的结果会影响到第二步 , 第二步结果会影响第三步 3 Promise.then().then().then().catch() 捕获异常用window.addEventListener new Promise((resolve,reject)=>{ resove('ok') // 传递给.then reject(err) // 传递catch }) 三个状态: Pending 进行中 fulfilled 成功 Rejected 失败 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。 async --- await async function () { } 返回promise对象 await 将异步转成同步 同步有返回值 Promise.all() 里面参数全部执行 与then同级的另一个方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。 Promise.race() 哪个快就执行哪个,不管是失败还是成功

 

1.promise语法 new Promise(function (resolve, reject) { // resolve 表示成功的回调 // reject 表示失败的回调 }).then(function (res) { // 成功的函数 }).catch(function (err) { // 失败的函数 }) 2.async/await语法 async function fn() { const res = await promise对象 } -------------------------------------------------- Promise.prototype.then 方法返回的是一个新的 Promise 对象,因此可以采用链式写法。 getJSON("/posts.json").then(function(json) { return json.post; }).then(function(post) { // proceed }); 上面的代码使用 then 方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。 如果前一个回调函数返回的是Promise对象,这时后一个回调函数就会等待该Promise对象有了运行结果,才会进一步调用。 Promise.prototype.catch 方法是 Promise.prototype.then(null, rejection) 的别名,用于指定发生错误时的回调函数。

 

promise是解决异步回调,回调地狱问题,因为js本身就是异步语言,如果是同步就不会出现这种问题,它靠的是事件轮询,事件环,什么完成了就进行回调,并不是根据我们排好的顺序进行回调, 比如说 函数1完成后结果给2用,函数2完成后结果给三用,如果是这样的话,普通函数就不行了,很有可能是2先执行完,我们可能加一个所谓的判断,判断1完成后调用2,2完成后执行3,这样就会嵌套成回调地狱,而且代码不好维护, 所以,我们就要用到 promise,他里面有 .then() .catch() 的链式语法,里面可以有好多个.then()最后才是 .catch,这个一定是第一个 .then()执行完,执行第二个,依次执行,最后是.catch(),就是一个之前不确定的顺序,最后通过这种链式语法来确定,相当于把它变成同步的链式语法,而且比较好维护

 

2 let const var 区别

let,const 会产生块及作用域 ,声明的变量就是私有的 var 变量提升(预解析) let const 没有 let 可以修改 但是不可重复声明 const 不可以修改 复杂类型可以改变 我们一般定义 常量 配置属性 使用的一般我们会根据 作用域来选 ----- 解决了 变量渲染全局的问题 ----- 有点类似闭包的特性

 

3 箭头函数

特点:不可以new、没有arguments 1 使用情况 在vue和react或者其他框架里面,我们一般情况下 this都应该指向当前组件 , 如果用普通函数会导致this指向不明确,所以用箭头函数比较合适 2 箭头函数的this始终指向它的外部环境,不会发生改变 3 let foo = () => {} 后面有没有大括号是两种 如果有大括号就是普通函数 如果不加大括号 自动加return 4 不能能做构造函数 因为this指向固话 5 箭头函数没有 arguments对象 (获取实参的集合), 我们可以通过 ...拓展运算符来模拟实参集合 普通函数的this指向 call bind apply call和bind的区别:call直接调用,bind返回一个新函数,需要手动调用 改变指向/ 区别点:             // call和apply会调用函数,并且改变函数内部this指向             // call和apply传递的参数不一样,call传递参数为aru1,aru2...的形式,apply必须数组形式[aru1,aru2...]             // bind不会调用函数,可以改变函数内部this指向         // 主要应用场景:             // call 经常做继承             // apply 经常跟数组有关系,比如借助于数学对象实现数组最大值最小值             // bind 不调用函数,但是还想改变this指向,比如改变定时器内部的this指向

 

箭头函数只能简写函数表达式,不能简写声明式函数 语法: (函数的行参) => { 函数体内要执行的代码 } 箭头函数内部没有 this,箭头函数的 this 是上下文的 this 箭头函数内部没有 arguments 这个参数集合 函数的行参只有一个的时候可以不写 ()其余情况必须写 函数体只有一行代码的时候,可以不写 {},并且会自动 return 一句代码,不需要return的时候,要写{ } 一句代码,需要return的时候,可以不写{ } 返回一个对象的时候,要写成({ })

 

new的意义

实例化对象 把函数变为自定义构造函数 改变了函数内的this 指向了构造函数 自动返回了一个对象 prototype 和__proto__指向了同一个地址

 

4 解构赋值

a=10 b=11 [b,a]= [a,b]

 

解构对象 const obj = { name: 'Jack', age: 18, gender: '男' } let { name, age, gender } = obj 解构数组 const arr = ['Jack', 'Rose', 'Tom'] let [a, b, c] = arr

 

5 模板字符串

` ${} `

 

let num = 100 let str = `hello${num}world${num}` console.log(str) // hello100world100

 

6 class 类

class Person {} class Man extends Preson{ constructor(){ super() } }

 

// 下面表示创造一个 Student 类,继承自 Person 类 class Student extends Person { constructor () { // 必须在 constructor 里面执行一下 super() 完成继承 super() } }

 

7 Set ,Map 去重

arr = [...new Set(arr)] set.add()添加 set.has()判断有没有

 

https://www.cnblogs.com/leftJS/p/11080962.html 1.set类似于数组,但是成员的值都是唯一的,没有重复的值。 (1)实例对象方法 add(value):添加某个值,返回 Set 结构本身(可以链式调用)。 delete(value):删除某个值,删除成功返回true,否则返回false。 has(value):返回一个布尔值,表示该值是否为Set的成员。 clear():清除所有成员,没有返回值。 const mySet = new Set(['a', 'a', 'b', 1, 2, 1]) console.log(mySet) // {'a', 'b', 1, 2} 然后使用Array.from将对象转为数组 myset.add('c').add({'a': 1}) console.log(mySet) // {'a', 'b', 1, 2, 'c', {a: 1}} console.log(mySet.size) // 6 mySet.has(2) // true (2)遍历方法 keys():返回键名的遍历器。 values():返回键值的遍历器。 entries():返回键值对的遍历器。 forEach():使用回调函数遍历每个成员。 (3)数组去重 function unique(arr){ return [...(new Set(arr))]; } 2.map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。 (1)map对象的方法 set(key, val): 向Map中添加新元素 get(key): 通过键值查找特定的数值并返回 has(key): 判断Map对象中是否有Key所对应的值,有返回true,否则返回false delete(key): 通过键值从Map中移除对应的数据 clear(): 将这个Map中的所有元素删除 const m1 = new Map([['a', 111], ['b', 222]]) console.log(m1) // {"a" => 111, "b" => 222} m1.get('a') // 111 const m2 = new Map([['c', 3]]) {"c" => 3 } const m3 = new Map(m2) m3.get('c') // 3 m3.has('c') // true m3.set('d', 555) m3.get('d') // 555 (2)遍历方法 keys():返回键名的遍历器 values():返回键值的遍历器 entries():返回键值对的遍历器 forEach():使用回调函数遍历每个成员 (3)数组去重 function unique(arr) { //定义常量 res,值为一个Map对象实例 const res = new Map(); //返回arr数组过滤后的结果,结果为一个数组 //过滤条件是,如果res中没有某个键,就设置这个键的值为1 return arr.filter((a) => !res.has(a) && res.set(a, 1)) }

 

8 对象的简写 新增的对象方法

Object.assign({},obj1,obj2) //合并对象 {...} Object.frzze() 创建不可更改的对象 Object.defineProperty() ****** vue 双向数据绑定原理 2.0 ---- 3XXX使用的不是这个 Proxy (代理不是一会儿) 利用 原生 Object.defineProperty 这个方法来监听和改变值的, defineProperty 有两个函数 一个set,一个是get get函数 使用数据就触发 -- 调用数据的时候触发 get方法来进行同步数据 set函数 修改数据的时候触发 渲染视图的方法 render()

 

9 symbol 唯一

为了给对象添加key值来使用

 

10 数组的方法(新增)

include 是否包含 find((item) //返回是元素 有一个满足就会返回 findIndex((item)) //返回值下标 es5遍历 filter 会组成新数组 map 有返回值 every 有一个不满足就会返回 false some 有满足就会返回true redcuer((第一个参数,后面的每一个参数)=>) //求和 forEach 没有返回值 , 没有break 如果操作数组会改原数组 map 生成新数组 , 必须有返回值 , 它的返回值会创建一个集合

 

11 ... 拓展运算符 浅拷贝/深拷贝

let arr = [1,2,3,4,5] let arr1 = [...arr] 浅拷贝 let obj = {name:"zzz"} let obb1 = {...obj} 模拟arguments 获取实参的集合 箭头没有arguments对象 1、浅拷贝 概念:子对象复制父对象,父子对象发生关联,两者属性值指向同一内存空间。简单来讲,就是改变其中一个对象,另一个对象也会跟着改变。 深拷贝 2、深拷贝 概念:拷贝对象各个层级的属性。简单的讲,就是复制出来的每个对象都有属于自己的内存空间,不会互相干扰。 SON对象的 parse 和 stringify

 

12 symbol 唯一 用做key值

1.Symbol 本质上是一种唯一标识符,可用作对象的唯一属性名,这样其他人就不会改写或覆盖你设置的属性值。 2.声明方法:let id = Symbol("id"); 3.Symbol 数据类型的特点是唯一性,即使是用同一个变量生成的值也不相等。 let id1 = Symbol('id'); let id2 = Symbol('id'); console.log(id1 == id2); //false 4.Symbol 数据类型的另一特点是隐藏性,for···in,object.keys() 不能访问

 

13 本地存储

cookie (一般情况下 cookie都是从后台发送的) web存储 (低版本不兼容) localStorage (长存) sesstionStorage (会话 关闭浏览器销毁) if(localStorage){ 使用localStorage }else{ cookie }

 

1.cookie: cookie是一个以字符串的形式存储数据的位置,在字符串中以key=value的形式出现,每一个key=value是一条数据,多个数据之间以 ; 分割。每一个 HTTP 请求都会在请求头中携带 cookie 到服务端,每一个 HTTP 响应都会在响应头中携带 cookie 到客户端,也就是,cookie 是不需要我们手动设置,就会自动在 客户端 和 服务端之间游走的数据。 读取cookie: const cookie = document.cookie console.log(cookie) // 就能得到当前 cookie 的值 设置cookie: // 下面这个 cookie 数据会在 2043 年 12 月 18 日 12 点以后过期,过期后会自动消失 document.cookie = 'b=200;expires=Thu, 18 Dec 2043 12:00:00 GMT";' 删除cookie: // 因为 cookie 不能直接删除 // 所以我们只能把某一条 cookie 的过期时间设置成当前时间之前 // 那么浏览器就会自动删除 cookie document.cookie = 'b=200;expires=Thu, 18 Dec 2018 12:00:00 GMT";' 2.localStorage 本地存储: 没有过期时间,不会跟随服务器发送,大小5M,不用在服务器下运行。 // 设置 localStorage.setItem('item', 'abc') // 获取 console.log(localStorage.getItem('item')) // 删除 localStorage.removeItem('item') // 清空 localStorage.clear() 3.sessionStorage 本地存储: 会话结束就没有了,不会跟随服务器发送,大小5M,不用在服务器下运行,写法和localStorage完全一样。 // 设置 sessionStorage.setItem('item', 'abc') // 获取 console.log(sessionStorage.getItem('item')) // 删除 sessionStorage.removeItem('item') // 清空 sessionStorage.clear()

 

14 地址栏输入网址过程中发生了什么

1 解析域名 查看本地dns是否存贮 -- 直接返回 2 向服务器发送Http请求 3 服务器返回响应的资源 4 浏览器会进行重排和重绘 -- 浏览器解析页面呈现页面 5 会把请求的内容存储到dns

 

15 跨域

1 同源策略 协议 域名 端口号 部署到同原 什么是同源策略: 同源策略是浏览器众多重要的安全措施之一,它规定不同源的客户端脚本在没明确授权的情况下,不能读写对方的资源。 一个源由三个部分确定:协议(http与https)域名(顶域与子域,不同的子域)端口;这三个元素都要相同才是在同一个源下。 客户端脚本主要是指JavaScript和ActionScript(Flash)。 授权:服务器通过某种方式告诉浏览器,另一个域下的脚本可以访问我。 资源:HTTP头,DOM树,Cookie,localStorage等。 2 cors 服务器设置响应头 允许访问 Access-Control-Allow-Origin 后端设置访问权限(不常用) 3 vue、react 使用webpack代理 (开发过程中有用) 打包之后不生效 Vue: proxy: { "/api": { target: "http://192.168.x.xxx:8090", // 要访问的接口域名 ws: true, // 是否启用websockets changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题 pathRewrite: { "^/api": "", //这里理解成用'/api'代替target里面的地址,比如我要调用'http://40.00.100.100:3002/user/add',直接写'/api/user/add'即可 }, }, } react: 创建src/setupProxy.js const proxy = require("http-proxy-middleware"); module.exports = function(app){ app.use( proxy("/api",{ target:"http://127.0.0.1:8089/", changeOrigin:true, pathRewrite:{ '/api':'' } ) } 4 jsonp 原理 纯前端技术跨域(需要后端配合) src请求不需要跨域,后台返回一个调用函数,返回函数的实参就是后台返回的数据 第三方公司可能会使用jsonp 1) src去访问的时候不受同源策略影响defineproperty 2) 提供过动态创建 script 在script的src属性上发请求 <script src="http://127.0.0.1:8089/user?cb=fn1"></script> 3) 后端会返回一个函数的调用 里面参数就是后端给的数据 fn1({code:200,msg:"ok",data:[]}) 4) 前端需要声明函数 5) 要通过地址把函数名传递给后端,后端动态调用函数 a 6) jsonp 一定是get请求 5 iframe 两个项目页面与页面之间传递---跨域 stoppropagetion iframe src document.domain 6 websocket(用于实时通讯) ws:// 可以做跨域 7 nginx 反向代理 做 负载均衡 (不知道访问的是哪里) (不知道是谁访问---正向代理) 后台设置

 

https://juejin.im/post/6844904126246027278?utm_source=wechat_session&utm_medium=social&utm_oi=665117609675198464#heading-28 1 同源策略:请求协议/域名/端口号全部相同。 2 CORS:跨域资源共享(浏览器自带机制) 跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。对于前端来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,实现CORS通信的关键是服务器。 Node 中的解决方案 直接使用中间件 const cors = require("koa-cors"); app.use(cors()); 传递cookie前端需设置 withCredentials: true,后端需设置Access-Control-Allow-Credentials为true,Access-Control-Allow-Origin不为* 3 nginx反向代理 (1)安装nginx (2)配置nginx,把localhost:8080和localhost:8000统一配置在统一服务器local.test(自定义域名)下。 server { listen 80; server_name local.test; location /api { proxy_pass http://localhost:8080; } location / { proxy_pass http://localhost:8000; } } (3)重启nginx (4)前端请求 <script>  axios.defaults.withCredentials = true;  login.onclick = () => {  axios.post("/api/login"); }; </script> 4 使用webpack代理(开发过程中有用,打包之后不生效) 配置webpack中的devServe devServer: { open: true, host: 'localhost', port: 8000, https: false, hotOnly: false, proxy: { // 配置跨域 '/api': { target: 'http://localhost:8080/', // 要访问的接口域名 ws: true, // 是否启用websockets changOrigin: true, //开启代理 pathRewrite: { '^/api': '' //这里理解成用'/api'代替target里面的地址,比如我要调 用'http://localhost:8080/login',直接写'/api/login'即可 } } }, before: app => { } } 5 jsonp跨域 (1)script 标签的 src 属性本质就是请求一个外部资源,是不受到同源策略的影响的。并且请求回来的东西是一个字符串,浏览器会把这个字符串当作 js 代码来执行。所以我们就可以利用这个 script 标签的 src 属性来进行跨域请求。 <script> var script=document.createElement('script') function getData(data){ console.log(data) } script.src='http://localhost:8080?callback=getData' document.body.appendChild(script) </script> (2)使用Jquery封装函数$.ajax $.ajax({ url: "http://127.0.0.1:8081/list", dataType: "jsonp", success: (res) => { console.log(res) }, });

 

16 http状态码

链接 https://www.jianshu.com/p/eed60f57b7b7?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation 2xx 成功

200 最常见 请求成功ok

202 请求但是尚未处理

3xx 重定向 4xx

400 请求语法错误

401 发送请求时候需要http认证

403 表明对请求资源的访问被服务器拒绝了, 超出访问权限

404 请求地址或者请求方式发生错误

5XX 服务器那端的代码不一致

500 服务器定义的内容前端定义的不一致 --

503 后端维护服务器

 

17 post传参与get传参的区别

1 post 上传 都可以用post 2 get 明文请求 jsonp必须用get 请求内容在地址栏显示 不安全 1、传送方式:get通过地址栏传输,post通过请求体传输。 2、传送长度:get参数有长度限制(受限于url长度),而post无限制 3、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式; 2 post传参 容易发送两次请求 1 跨域检验 options请求 -- 闭 2 才会发送post请求 post请求转数据格式 这三种不需要检验跨域 x-www-from-urlencoded formData text/plain axios默认格式永远 applcaition/json import qs from "qs" 1) axios.default.post["Content-Type"] = "application/x-www-from-urlencoded;chaset=utf8" post请求的数据 需要 qs.stringify进行反序列化 data:qs.stringify(data)

 

18 事件流 冒泡和 捕获

冒泡 -- 从内向外 -- 事件委托 捕获 -- 从外向内 -- 改热键 div.addEventListener("click",function(){},false) -- removeEventLisener div.οnclick=function(){}

 

1. 冒泡: 就是从事件目标的事件处理函数开始,依次向外,直到 window 的事件处理函数触发,也就是从下向上的执行事件处理函数 2. 捕获: 就是从 window 的事件处理函数开始,依次向内,直到事件目标的事件处理函数执行,也就是从上向下的执行事件处理函数 事件触发默认冒泡,从内向外触发。 阻止冒泡的几种方式: (1) e.stopPropagation() 点击只出现li

<ul> <li>1</li> </ul>

<script>

var ul = document.querySelector('ul')

var li = document.querySelector('li')

li.addEventListener('click', function (e) { e.stopPropagation() console.log('li') }) ul.addEventListener('click', function () { console.log('ul') })

</script>

(2)e.cancelBubble = true 点击只出现li <ul> <li>1</li> </ul> <script> var ul = document.querySelector('ul') var li = document.querySelector('li') li.addEventListener('click', function (e) { e.cancelBubble = true console.log('li') }) ul.addEventListener('click', function () { console.log('ul') }) </script>

(3)事件监听第三个参数true,事件捕获,默认false,事件冒泡。冒泡先出现li,再出现ul。捕获先出现ul,再出现li。

<ul> <li>1</li> </ul>

<script> var ul = document.querySelector('ul') var li = document.querySelector('li') li.addEventListener('click', function (e) { console.log('li') }) ul.addEventListener('click', function () { console.log('ul') },true) </script>

 

19 作用域链

作用域 外部访问不到内部变量 -- 闭包 内部可以放外部 我们是调用一个变量的时候 会从他自己的作用域开始查找,找到就返回,找不到会想外层找,找到返回,找不到向外层找 以此类推, 如果最外层全局还不到就报错 is not defined

 

20 防抖 和 节流

防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间 节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率 区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。 ---------------- 1 使用场景 1 ) 搜索的时候 , 很容易重复触发请求,怎么避免这个问题 2 ) 根据移动坐标来触发验证 , 滑动验证码 https://segmentfault.com/a/1190000018428170 看看文章 ()

 

防抖是将多次执行变为只执行一次(开关锁),节流是将多次执行变为每隔一段时间执行(清零)。   1. 防抖:(滚动事件) 防抖,一段时间内执行一次,核心在于开关锁 timer=null 对于短时间内连续触发的事件(如滚动事件),防抖的含义就是让某个时间期限内,事件处理函数只执行一次。 function debounce(fn,delay){ let timer = null //借助闭包 return function() { if(timer){ clearTimeout(timer) } timer = setTimeout(fn,delay) // 简化写法 } } function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;   console.log('滚动条位置:' + scrollTop); } window.onscroll = debounce(showTop,1000) 2. 节流: 核心在于清零 clearTimeout(timer) 如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。 function throttle(fn,delay){ let valid = true return function() { if(!valid){ //休息时间 暂不接客 return false } // 工作时间,执行函数并且在间隔期内把状态位设为无效 valid = false setTimeout(() => { fn() valid = true; }, delay) } } function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;   console.log('滚动条位置:' + scrollTop); } window.onscroll = throttle(showTop,1000)

 

21 react

react全家桶:react + react-router + redux + axios 类组件 1 setState({}) 异步 1 setState 会执行render 2 setState多次 合并 将多个状态合并一起更新 减少render的调用 3 setState((prevState,prevProps)=>({})) setState({})为什么异步? 生命周期 setState 改变了状态并触发了 render, 而 render 往往是伴随着重绘和回流的,显然,这是非常影响浏览器性能的操作。如果设计成同步的话,试想,假使多个组件绑定了一个合成事件处理函数,那么,当这个事件函数执行的时候,setState 会多次修改 state 并 render。我们不如在 setState 的时候先不触发,而是先把那些需要更改的组件标记一下,最后一起改变 state 并渲染,这对浏览器性能的提升显然是有积极的影响的。 this.setState({},callback) callback数据修改完成之后执行 this.setState((prevState,prevProps)=>({}),callback) 2 生命周期 -- 三五分钟 更新的生命周期 shouldcomponentupdate(nextProps,nextState){ return } 3 高阶组件 自定义高阶组件 组件通信 父传子 子传父 redux ref this.props.children 插槽 {this.props.children} {/* 这里接受<SiderDemo>XXX</SiderDemo>传过来的XXX */} 4 context 跨组件通信 只要包裹根组件,所有的子代组件都可以使用这个数据 <context.Provider> <App /> </context.Provider> <context.Consumer> { data=>data就是共享的数据 } </context.Consumer> Router react-redux 5 redux reducer(state,action){ swich(){ case ADD } } getState() //获取状态 dispatch({type:"ADD"}) 触发行为 action createStore() 数据模块化 //subscribe() react-redux <Provider></Prvider> connenct(mapStateToProps,mapDispatchToProps)(app) 6 hook let [n,setN] = useState(0) useEffect(()=>{},[]) useRef() useMemo() useCallback() useContext useReducer 7 react与vue的优缺点?

 

22 react生命周期

最早的一个生命周期 constructro(){ super() } 挂载阶段 1.componentWillMount 发生在 render 函数之前,还没有挂载 Dom 2.render 3.componentDidMount 发生在 render 函数之后,已经挂载 Dom 更新阶段 * 1. componentWillReceiveProps * 2. shouldComponentUpdate * 3. componentWillUpdate * 4. componentDidUpdate 卸载阶段 componentWillUnmount 触发条件 父组件数据改变 自己的数据改变 触发条件 只有父组件render的时候才会触发 它的作用 同步state componentWillReceiveProps(nextProps,nextState){ this.setState({ m:nextProps.n }) } // 这种写法 不适应与 引用类型 引用类型需要 先转成字符串进行值比较 使用再转成对象 shouldComponentUpdate(){ //优化性能的方案 return Object.keys(nextState).some(key=> nextState[key] !== this.state[key]) || Object.keys(nextProps).some(key=> nextProps[key] !== this.props[key]) } //组件将要更新 没啥用 componentWillUpdate(nextProps,nextState){} // render() // 组件更新完成之后执行 componentDidUpdate(prevProps,prevState){ // 数据更细完成之后才会执行 --- 无论哪个数据更新完之后都会执行 // } 卸载阶段 componentWillUnmount 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount 中创建的订阅等。componentWillUnmount 中不应调用 setState,因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

 

23 react 路由传参

<Link to={ {pathname:"/detail",state:{}}}></Link> 路由两种模式 都能存储传递的值 query不能使用 刷新不保存 hash 想保存值 需要用 search:"name=zzz&age=20" 在导航栏拼接字符串 history state:{name:"zhangsan"}

 

24 微信小程序

1 上线流程 注册账号 下载开发工具 创建项目正常开发 可以.... 开发的时候需要 设置 不校验合法域名 开发完成之后 小程序平台 配置 合法域名 上传代码 大小不能超过 1个包 不超过2m 多个包 最大不能超过20m 提交审核 -- 通过 发布代码 2 传参 事件传参 data-自定义属性 e.currentTarget.dataset.自定属性 3 路由传参 ?拼接地址的方法 在生命周期 onload(options) 4 <navigator open-type=""></navigator> 1 navigate 正常跳转 2 switchTab tarBar 3 redirect 替换 4 relanugh 删除之前的并跳转 ..... 5 小程序的运行原理 没有给页面 .wxml 结构 .wxss 样式 .js 逻辑 .json 配置 6 你做过微信小程序? 7 小程序的优势? 8 云开发 -- 云数据库

 

25 uniapp

vue开发小程序 --- vue开发小程序 最后可以打包app vue的语法 开发各种软件的工具 同一套代码 可以打包成 app 也可以转换成各种小程序

 

26 混合开发

h5+安卓 h5+ios 怎么交互 <webview src="h5页面" /> 1 前端 window.saoma=function(data){ //data } 2 原生 扫码信息拿到 window.saoma(扫码信息拿到)

 

27 VUE

1 MVVM是什么?

https://www.cnblogs.com/wzfwaf/p/10553160.html

前后端分离:Model用纯JavaScript对象表示,View负责显示。

model:服务器的业务逻辑操作

view:用户界面

ViewModel:核心枢纽 过程:把view和model关联起来的就是View Model。

ViewModel负责吧Model的数据同步到view显出来,还负责吧view修改同步到Model。

1. 各部分之间的通信,都是双向的。

2. View 与 Model 不发生联系,都通过ViewModel传递。

三.双向绑定是什么原理,能写出来吗?

大大减轻开发负担,自动化处理。

双向绑定:data和view之间的自动化处理 2 组件通信?

this.$parent --- 比较常用 this.$children ref mixin:[组件1,组件2] [重要]

$root eventBus 3 v-if v-show区别 4 methods,computed,watch methods:强调的主观调用 computed,watch:自动调用

1 使用选择 推荐使用 computed

2 如果监听的数据会影响多个数据 那么watch

3 如果多个值影响一个值 computed

4 如果 设计到异步ajax那么只能使用watch ***

5 计算属性会有值的缓存

6 watch 出发的时候有间隔 (相当于做了节流了) watch : set函数 conputed: get函数 5 keepAlive -------- 相当于react请求中存储在本地

1 缓存组件 一般 <keep-alive> router-view </keep-alive> 应该销毁的组件没有销毁 (闭包 -- 函数) (项目启动过程中缓存)

2 两个生命周期 actived(){} //进入的时候执行 deactived(){} //离开的时候会执行

3 设置是否需要缓存 include exclude 填写的是组件的name值 6 vuex vuex不一定非用不可,多组件之间共享数据,(维护简单) state 存储状态 mutations 修改状态 getter 计算属性 actions 异步请求数据 -- commit("mutaitions") module:{}, puligins:[] 用户信息 订单信息 评论 7 路由 1 路由传参 动态路由 /user/:id 2 路由的生命周期 --- 验证是否等 登录---> 会在本地存储一个状态 --- 全局钩子 beforeEach((to,from,next)) 但是--前端不安全的验证 -- 因为本地存储的数据可以改 真安全访问的 还得跟后台传token 让后台验证token token 请求头里面 3 mode:"hash/history" history 容易出现404 需要服务端配置 资源路径访问的问题 4 后台管理系统 动态路由改变路由表 1 如果权限单一 直接通过 后端传递 用户权限字段来判断 role v-if="" 2 如果权限复杂 动态生成路由表 --- 动态修改 routes 登录的时候 根据你的角色 给你路由表 如果问道 路由传参 传参了 内容不变 监听路由

8 自定义指令 vue.directive() 自定义过滤器 vue.filter()

9 生命周期 常见8个

10 key值 添加唯一标识 1) 添加删除的时候 回去直接处理改变的 2) 当你加Key的组件如果key改变 它会自动跟新

11 vue请求数据放在created好还是mounted里好 **建议放在created里** **created**:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。 **mounted**:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。

如果在**mounted**钩子函数中请求数据可能导致页面闪屏问题 其实就是加载时机问题,放在**created**里会比**mounted**触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了 由于 JavaScript 的限制,Vue 不能检测以下数组的变动: ```javascript var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是响应性的 vm.items.length = 2 // 不是响应性的 ``` 当利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue 可以使用: Vue.set(vm.items, indexOfItem, newValue);或者:vm.$set(vm.items, indexOfItem, newValue) vm.items.splice(indexOfItem, 1, newValue) 当修改数组的长度时,例如:vm.items.length = newLength 可以使用:vm.items.splice(newLength) 由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除: 因为Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

 

28 鉴权

后台管理系统 1 动态设置路由显示哪些页面 2 前端 v-if v-show

 

29 webpack 基础

entry :入口文件 多页应用 多入口多出口 output: 出口文件 module:{ loader rules:[] } plugins:[ ], devServer:{} //webpack服务器

 

const path = require("path"); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: "development", entry: "./src/main.js", //入口文件 output: { //口文件 filename: "main.js", path: path.join(__dirname, "../dist"), }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.scss$/, use: [ { loader: "style-loader", // 将 JS 字符串生成为 style 节点 }, { loader: "css-loader", // 将 CSS 转化成 CommonJS 模块 }, { loader: "sass-loader", // 将 Sass 编译成 CSS }, ], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "./index.html" }), ], devServer: { // contentBase: path.join(__dirname, "../dist"), port: 3000, //端口号 open: true, //是否自动打开浏览器 hot: true, // 热更新 proxy: { '/api': {// '/api':匹配项 target: 'http://www.baidu.com',// 接口的域名 // secure: false,// 如果是https接口,需要配置这个参数 changeOrigin: true,// 如果接口跨域,需要进行这个参数配置 // pathRewrite: {// 如果接口本身没有/api需要通过pathRewrite来重写了地址 // '^api': '' // } } } } }  **Proxy** webpack中的`proxy`只是一层代理,用于把指定的`path`,代理去后端提供的地址,背后使用node来做server。可能有人疑惑,为什么只适用本地开发?因为该技术只是在webpack打包阶段在本地临时生成了node server,来实现类似nginx 的`proxy_pass`的反向代理效果   `proxy`工作原理实质上是利用`http-proxy-middleware` 这个http代理中间件,实现请求转发给其他服务器。例如:本地主机A为`http://localhost:3000`,该主机浏览器发送一个请求,接口为`/api`,这个请求的数据(响应)在另外一台服务器B`http://10.231.133.22:80`上,这时,就可以通过A主机设置webpack proxy,直接将请求发送给B主机。

 

30 服务端渲染

next.js

 

31 ajax

前后端交互技术 核心两个 XMLHttpRequest --- $.ajax axios fetch -- fetch 1 ajax 原理 1) 获取核心对象 做兼容

2) 发送请求 xhr.open("methods",url,true)

3) 发送参数 xhr.send(null)

4) 监听变化触发函数 xhr.onreadystatechange 2 axios 二次分装 请求拦截器 修改参数类型 , 统一传固定参数 。。。 相应拦截器 错误几种处理 3 $.ajax 当你想用 jsonp的时候 用封装$.ajax

 

1. ajax: ajax全名async javascript and XML(异步的javascript和XML),客户端给服务端发送消息的工具,以及接受响应的工具。 (1)创建一个 ajax 对象 const xhr = new XMLHttpRequest() (2)配置链接信息 // xhr.open('请求方式', '请求地址', 是否异步默认 true 表示异步false 表示同步) xhr.open('get', './data.php') (3)发送请求 xhr.send() (4)获得相应数据 // ajax状态码 xhr.readyState,只有当 readyState === 4 的时候,我们才可以正常使用服务端给我们的数据 // 记录http状态码 xhr.status,200 ~ 299 表示本次请求成功了 // readyStateChange事件专门用来监听ajax对象 // responseText用来记录服务端给我们的响应体内容的 xhr.onreadyStateChange = function () { if (xhr.readyState === 4 && /^2\d{2|$/.test(xhr.status)) { console.log(xhr.responseText) } } (5)发送参数 // get 请求的参数就直接在 url 后面进行拼接就可以 xhr.open('get', './data.php?a=100&b=200') // post 请求的参数是携带在请求体中的,必须要先设置一下请求头中的 content-type // application/x-www-form-urlencoded 表示的数据格式就是 key=value&key=value xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') xhr.send('a=100&b=200') 2. axios: (1)设置拦截器 import axios from "axios"; const fetchData = axios.create({ baseURL: "http://localhost:3000", // 请求地址前缀 withCredentials: true, // 允许携带cookie }); //添加请求拦截器 fetchData.interceptors.request.use( function (config) { if (config.method == "get") { config.params = { ...config.params, token: JSON.parse(localStorage.getItem("user")).token, //携带token cookie: JSON.parse(localStorage.getItem("user")).cookie, //携带cookie }; } if (config.method == "post") { config.data = { ...config.data, token: JSON.parse(localStorage.getItem("user")).token, //携带token cookie: JSON.parse(localStorage.getItem("user")).cookie, //携带cookie }; } return config; }, function (error) { //请求错误时做些事 return Promise.reject(error); } ); //添加响应拦截器 fetchData.interceptors.response.use( function (response) { //对响应数据做些事 return response; }, function (error) { //响应错误时做些事 return Promise.reject(error); } ); export default fetchData; (2)二次封装 // 导入拦截器 import fetchData from "./fetchData"; // get请求用params传参 export async function getPlayList(data = {}) { return await fetchData.get("/top/playlist", { params: data, }); } // post请求用data传参 export async function login(data) { return await fetchData.post("/login/cellphone", data); } 3. jsonp: (1)script 标签的 src 属性本质就是请求一个外部资源,是不受到同源策略的影响的。并且请求回来的东西是一个字符串,浏览器会把这个字符串当作 js 代码来执行。所以我们就可以利用这个 script 标签的 src 属性来进行跨域请求。 (2)使用Jquery封装函数$.ajax $.ajax({ url: "http://127.0.0.1:8081/list", dataType: "jsonp", success: (res) => { console.log(res) }, });

 

32 事件委托 提高性能

1 利用的是冒泡原理 ,将事件注册给父辈组件,因为冒泡点击本身的时候父组件会触发,可以通过判断事件源,来判断是谁触发的从而实现事件委托 2 减少了事件注册 , 动态添加的元素依然会享有事件

 

事件委托: 可以给未来元素添加事件 <body> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script> var oUl = docuemnt.querySelector('ul') oUl.addEventListener('click', function (e) { e = e || window.event var target = e.target || e.srcElement if (target.nodeName === 'LI') { console.log('我是 li,我被点击了') } }) </script> </body>

 

33 当你输入网址的时候经历了什么?

1.解析域名 查看本地DNS是否存储----若存储直接返回IP 2.向服务器发送Http请求 3.服务器返回响应资源 4.浏览器进行重排和重绘--浏览器解析页面 5.会把请求存储到DNS

 

https://segmentfault.com/a/1190000006879700

 

1.DNS解析:DNS解析的过程就是网址到IP地址的转换,当发送请求时,可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡。 2.TCP连接 TCP/IP 协议 三次握手: (1)客户端发送一个消息给到服务端 (2)服务端回给客户端一个消息 (3)客户端再回给服务端一个消息 四次挥手: (1)客户端发送一个我要断开的消息给服务端 (2)服务端接受到以后发送一个消息告诉客户端我已经进入关闭等待状态 (3)服务端再次发送一个消息告诉客户端,这个是我的最后一次消息给你,当我再接受到消息的时候就会关闭 (4)客户端接受到服务端的消息以后,告诉服务器,我已经关闭,这个是给你的最后一个消息 3.发送HTTP请求 每一个请求都会有一个请求报文(请求行,请求头,请求空行,请求体) 完整请求报文 (1)请求行 POST /user HTTP/1.1 # POST 请求方式 # /user 请求URL(不包含域名) # HTTP/1.1 请求协议版本 (2)请求头 user-agent: Mozilla/5.0 # 产生请求的浏览器信息 accept: application/json # 表示客户端希望接受的数据类型 Content-Type: application/x-www-form-urlencoded # 客户端发送的实体数据格式 Host: 127.0.0.1 # 请求的主机名(IP) (3)请求空行 #(此处必须有一空行 (3)请求体 name=world 4.服务器处理请求并返回HTTP报文 响应报文(状态行,响应头,响应体) (1)状态行 HTTP/1.1 200 OK # HTTP/1.1 服务器使用的 HTTP 协议版本 # 200 响应状态码 # OK 对响应状态码的简单解释 (2)响应头 Date: Jan, 14 Aug 2019 12:42:30 GMT # 服务器时间 Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45 # 服务器类型 Content-Type: text/html # 服务端给客户端的数据类型 Content-Length: 11 # 服务端给客户端的数据长度 (3)响应体 hello world # 服务端给客户端的响应数据 5.浏览器解析渲染页面 浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。 6.连接结束

 

34 Jquery

1 选择器 2 简单动画 animate hide show slideUp slideDown 3 attr removeAttr 4 ajax

 

35 Vue与Jquery区别

jquery开发 针对 每次修改dom 所有的思想是对于dom的修改, 好性能 Vue MVVM ,虚拟dom , 组件化开发会大大提高开发效率,维护效率,提高组减的复用, 自带很多指令,可以直接遍历dom,所达到修改数据后,视图会自动更新, vue 可以做单页应用,这样可以大量的减少http请求 vue 可以有想成缓存组件,更全面的 ui框架提供 vue 官方提供脚手架,当我开发的时候可以组件化,打包之后更是压缩文件,省去了我们原生开发还需要手动压缩 vue 逻辑实现比较简单,只要对数据增删改查就可以实现页面的增删改查

 

36 BFC(块级格式化上下文)

BFC(块级格式化上下文):它是一个独立的渲染区域,只有块级元素参与, 它规定了BFC内部的Block-level Box如何布局,并且与这个区域外部毫不相干。 BFC的布局规则(规定、标准): 一、BFC内部的Box会在垂直方向,一个接一个地放置。 二、Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠(按照最大margin值设置) 三、每个元素的margin box的左边, 与包含块border box的左边相接触 四、BFC的区域不会与float box重叠。 五、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。 六、计算BFC的高度时,浮动元素也参与计算 BFC的触发条件: 根元素(html) float属性不为none position为absolute或fixed display为inline-block, table-cell, table-caption, flex, inline-flex overflow不为visible 应用: 清除浮动 三栏布局

 

37 什么是nodejs?我们在哪里使用它?

Nodejs是服务器端的一门技术。它是基于Google V8 JavaScript引擎而开发的。用来开发可扩展的服务端程序。

 

38 为什么要使用node js?

nodejs会让我们的编程工作变得简单,它主要包含如下几点几个好处:   ①执行快速。   ②永远不会阻滞。   ③JavaScript是通用的编程语言。   ④异步处理机制。   ⑤避免并行所带来的问题。

 

39 nodejs有哪些特点?

是单线程的,但是有很高的可扩展性,使用JavaScript作为主流编程语言。使用的是异步处理机制和事件驱动。处理高效。

 

40 如何更新nodejs的版本?

npm install –g n n latest

 

41 为什么nodejs是单线程的?

Nodejs使用的是单线程没错,但是通过异步处理的方式,可以处理大量的数据吞吐量,从而有更好的性能和扩可扩展性。

 

42 什么是回调函数?

回调函数是指用一个函数作为参数传入另一个函数,这个函数会被在某个时机调用。

 

43 什么叫做回调地狱?

回调地狱是由嵌套的回调函数导致的。这样的机制会导致有些函数无法到达,并且很难维护。

 

44 如何阻止回调地狱?

有三种方法,对每个错误都要处理到,保证代码的贯通,程序代码模块化。

 

45 解释一下repl的作用?

Read evaluate print loop,用于测试,调试和实验用。

 

46 API函数的类型有哪些?

有两种:一种是阻滞型函数。阻滞型函数会等待操作完成以后再进行下一步。 另外一种是非阻滞型函数。这种函数使用回调函数来处理当前函数获取的结果。

 

47 回调函数的第1个参数是什么?

通常是错误对象。如果这个参数为空,表示没有错误。

 

48 NPM的作用是什么?

Node package manager,主要有两个功能。 它是一个网端模块的存储介质。 它的另一个作用是安装程序依赖和版本管理。

 

49 nodejs和ajax的区别是什么?

Nodejs和ajax也就是asynchronous JavaScript and xml,都是通过JavaScript来表现的,但是他们的目的截然不同。 Ajax是设计用来动态的更新页面的某个区域,从而不需要更新整个页面。 Nodejs是用来开发客户服务器类型应用的。

 

50 解释一下nodejs中chaining.

Chaining是指从一个数据流到另一个数据流的链接,从而实现多个流操作。

 

51 什么是streams?解释一下有哪些类型?

流的概念是不间断的,它可以不间断的从某个地方读取数据,或者向某个地方写入数据。 有4种类型的流数据。可读,可写。既可读,又可写,转化。

 

52 退出代码是什么?有哪些退出代码?

退出代码是指中断nodejs运行时返回的代码。   有这么几种unused, uncaught fatal exception, fatal error, non function internal exception handler, internal exception handler run time failure,internal JavaScript evaluation failure.

 

53 什么是globals?

  有三个global的关键字。   Global代表的是最上层的命名空间,用来管理所有其他的全局对象。   Process 是一个全局对象,可以把异步函数转化成异步回调, 它可以在任何地方被访问,它主要是用来返回系统的应用信息和环境信息.   Buffer, 是用来处理二进制数据的类.

 

54 Angular js和node js的区别是什么?

 Angular js是网络应用开发框架,而nodejs是一个实时系统。

 

55 为什么统一的风格儿非常重要,有什么工具可以保证这一点?

统一的风格可以让所有的组成员按照一种规矩来写代码。工具有Standard和eslint.

 

56 用什么方法来处理没有被处理的异常?

 在应用和node js之间使用domain来处理这样的异常。

 

57 Node js是如何支持多处理器平台的?

Cluster模块是用来支持这方面的。它可以允许多个nodejs工作进程运行在相同的端口上。

 

58 如何配置开发模式和生产模式的环境?

 首先有一个配置文件,然后通过环境变量参数来获取对应的配置内容。

 

59 nodejs中跟时间相关的函数有哪些?

 ①Set time out,clear time out.   ②Set interval,clear interval.   ③Set immediate,clear immediate.   ④Process.nextTick.

 

60 解释一下什么是reactor pattern。

Reactor pattern主要是非阻滞的i/o操作。提供一个回调函数来关联io操作。io请求完成以后会不会提交给demultiplexer, 这是一个通知接口用来处理并发性的非阻滞的io操作,这个功能是通过查询一个event loop来实现的.

 

61 lts版本是什么意思?

也就是long term support版本。至少会被支持18个月。使用的是偶数来标识。这种版本有稳定性和安全性的保证。

 

62 你为什么需要把express APP和server分开?

分开以后方便维护以及测试,在测试某个模块的时候,尤其是APP模块的时候,你不需要去对网络方面的连接配置做工作。

 

63 next tick和setImmediate的区别是什么?

Next tick会等待当前的event执行完成或者下一轮儿事件循环到达再执行。   Set immediate,会在下一轮的事件循环中,执行回调并且返回当前的循环来做读写操作。 Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。 Reducer Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

 


const reducer = function (state, action) {
 // ...
 return new_state;
};

整个应用的初始状态,可以作为 State 的默认值。下面是一个实际的例子。

 


const defaultState = 0;
const reducer = (state = defaultState, action) => {
 switch (action.type) {
   case 'ADD':
     return state + action.payload;
   default:
     return state;
}
};

const state = reducer(1, {
 type: 'ADD',
 payload: 2
});

上面代码中,`reducer`函数收到名为`ADD`的 Action 以后,就返回一个新的 State,作为加法的计算结果。其他运算的逻辑(比如减法),也可以根据 Action 的不同来实现。 实际应用中,Reducer 函数不用像上面这样手动调用,`store.dispatch`方法会触发 Reducer 的自动执行。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入`createStore`方法。

 


import { createStore } from 'redux';
const store = createStore(reducer);

上面代码中,createStore接受 Reducer 作为参数,生成一个新的 Store。以后每当store.dispatch发送过来一个新的 Action,就会自动调用 Reducer,得到新的 State。

为什么这个函数叫做 Reducer 呢?因为它可以作为数组的reduce方法的参数。请看下面的例子,一系列 Action 对象按照顺序作为一个数组。


const actions = [
{ type: 'ADD', payload: 0 },
{ type: 'ADD', payload: 1 },
{ type: 'ADD', payload: 2 }
];

const total = actions.reduce(reducer, 0); // 3

上面代码中,数组actions表示依次有三个 Action,分别是加0、加1和加2。数组的reduce方法接受 Reducer 函数作为参数,就可以直接得到最终的状态3。

Redux

(1)Web 应用是一个状态机,视图与状态是一一对应的。 (2)所有的状态,保存在一个对象里面。

 

1 Redux的基本概念

  • 整个应用只有唯一一个可信数据源,也就是只有一个 Store
  • State 只能通过触发 Action 来更改
  • State 的更改必须写成纯函数,也就是每次更改总是返回一个新的 State,在 Redux 里这种函数称为 Reducer

2 Actions

Action 很简单,就是一个单纯的包含 { type, payload } 的对象,type 是一个常量用来标示动作类型,payload 是这个动作携带的数据。Action 需要通过 store.dispatch() 方法来发送。

3 Store

现在有了 Action 和 Reducer,Store 的作用就是连接这两者,Store 的作用有这么几个:

  • Hold 住整个应用的 State 状态树
  • 提供一个 getState() 方法获取 State
  • 提供一个 dispatch() 方法发送 action 更改 State
  • 提供一个 subscribe() 方法注册回调函数监听 State 的更改

创建一个 Store 很容易,将 root reducer 函数传递给 createStore 方法即可:

```javascriptimport { createStore } from 'redux';import someApp from './reducers';let store = createStore(someApp);

// 你也可以额外指定一个初始 State(initialState),这对于服务端渲染很有用// let store = createStore(someApp, window.STATE_FROM_SERVER);

现在我们就拿到了 `store.dispatch`,可以用来分发 action 了: ```javascript let unsubscribe = store.subscribe(() => console.log(store.getState())); // Dispatch store.dispatch({ type: 'CHANGE_A' }); store.dispatch({ type: 'CHANGE_B', payload: 'Modified b' }); // Stop listening to state updates unsubscribe();

 

一、原型

①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象③所有引用类型的__proto__属性指向它构造函数的prototype

var a = [1,2,3]; a.__proto__ === Array.prototype; // true12
获取原型的方法

Object.getPrototypeOf(对象)


 

二、原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

11111111111111111111111111111111111111111111111111111110Promise是什么?

1、主要用于异步计算2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果3、可以在对象之间传递和操作promise,帮助我们处理队列

React版本17

antd版本4.8.2

vue版本4.7.8

webpack版本4.32.2

Node.js Express 框架


Express 简介

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。
  • 定义了路由表用于执行不同的 HTTP 请求动作。
  • 可以通过向模板传递参数来动态渲染 HTML 页面。NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:

NPM 使用介绍

    • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
    • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
    • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。1

Node.js REPL(交互式解释器)

Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Window 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。

Node 自带了交互式解释器,可以执行以下任务:

  • 读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
  • 执行 - 执行输入的数据结构
  • 打印 - 输出结果
  • 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

Node 的交互式解释器可以很好的调试 Javascript 代码。

什么是浏览器缓存

简单来说,浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为。

缓存的资源去哪里了?

你可能会有疑问,浏览器存储了资源,那它把资源存储在哪里呢?

memory cache

MemoryCache顾名思义,就是将资源缓存到内存中,等待下次访问时不需要重新下载资源,而直接从内存中获取。Webkit早已支持memoryCache。目前Webkit资源分成两类,一类是主资源,比如HTML页面,或者下载项,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接,分别对应代码中两个类:MainResourceLoader和SubresourceLoader。虽然Webkit支持memoryCache,但是也只是针对派生资源,它对应的类为CachedResource,用于保存原始数据(比如CSS,JS等),以及解码过的图片数据。

disk cache

DiskCache顾名思义,就是将资源缓存到磁盘中,等待下次访问时不需要重新下载资源,而直接从磁盘中获取,它的直接操作对象为CurlCacheManager。

  • |memory cache | disk cache

相同点

只能存储一些派生类资源文件

只能存储一些派生类资源文件

不同点

退出进程时数据会被清除

退出进程时数据不会被清除

存储资源

一般脚本、字体、图片会存在内存当中

一般非脚本会存在内存当中,如css等

因为CSS文件加载一次就可渲染出来,我们不会频繁读取它,所以它不适合缓存到内存中,但是js之类的脚本却随时可能会执行,如果脚本在磁盘当中,我们在执行脚本的时候需要从磁盘取到内存中来,这样IO开销就很大了,有可能导致浏览器失去响应。

三级缓存原理 (访问缓存优先级)

  1. 先在内存中查找,如果有,直接加载。
  2. 如果内存中不存在,则在硬盘中查找,如果有直接加载。
  3. 如果硬盘中也没有,那么就进行网络请求。
  4. 请求获取的资源缓存到硬盘和内存。
  5. Service Worker
  6. Memory Cache
  7. Disk Cache
  8. Push Cache

浏览器缓存的分类

  1. 强缓存
  2. 协商缓存

浏览器再向服务器请求资源时,首先判断是否命中强缓存,再判断是否命中协商缓存!

浏览器缓存的优点

1.减少了冗余的数据传输

2.减少了服务器的负担,大大提升了网站的性能

3.加快了客户端加载网页的速度

阻止冒泡相关的三种方法

1.event.stopPropagation();事件处理过程中,阻止了事件冒泡,但不会阻击默认行为

2.return false;事件处理过程中,阻止了事件冒泡,也阻止了默认行为

还有一种有冒泡有关的:3.event.preventDefault();它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为

SEO

搜索引擎优化 Vue nuxt.js React next.js

 

圣杯布局和双飞翼布局的作用和区别

圣杯布局和双飞翼布局解决的问题是一样的,就是两边顶宽,中间自适应的三栏布局,中间栏要在放在文档流前面以优先渲染。 圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏全部float浮动,但左右两栏加上负margin让其跟中间栏div并排,以形成三栏布局。 不同在于解决”中间栏div内容不被遮挡“问题的思路不一样: 圣杯布局,为了中间div内容不被遮挡,将中间div设置了左右padding-left和padding-right后,将左右两个div用相对布局position: relative并分别配合right和left属性,以便左右两栏div移动后不遮挡中间div。 双飞翼布局,为了中间div内容不被遮挡,直接在中间div内部创建子div用于放置内容,在该子div里用margin-left和margin-right为左右两栏div留出位置。 多了1个div,少用大致4个css属性(圣杯布局中间divpadding-left和padding-right这2个属性,加上左右两个div用相对布局position: relative及对应的right和left共4个属性,一共6个;而双飞翼布局子div里用margin-left和margin-right共2个属性,6-2=4),个人感觉比圣杯布局思路更直接和简洁一点。 简单说起来就是”双飞翼布局比圣杯布局多创建了一个div,但不用相对布局了“,而不是你题目中说的”去掉relative"就是双飞翼布局“。

 

1 会的技术栈有哪些?




 

2 混合开发用上H5plus 了吗?




 

3 微信小程序获取个人信息接口

vx.getuserinfo

 

4 Uniapp 用过吗?




 

5 Uniapp 页面的生命周期函数有那些?

onInit 监听页面初始化,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad onLoad 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参) onShow 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 onReady 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 onHide 监听页面隐藏 onUnload 监听页面卸载

 

6 Vue 什么时候开始使用的?




 

7 Vue 用的几版本?




 

8 Vue 脚手架的版本?

3版本

 

9 Vue 生命周期

beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据 created 实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data数据的初始化,el没有。 挂载阶段还没有开始, $el属性目前不可见,这是一个常用的生命周期,你可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理,也有一些童鞋喜欢在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成 beforeMount 挂载开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂载html到页面上。 mounted 挂载完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。 beforeUpdate 在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程 updated 在由于数据更改导致的虚拟DOM重新渲染和打补丁时会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用 beforeDestroy 在实例销毁之前调用,实例仍然完全可用,这一步还可以用this来获取实例,一般在这一步做一些重置的操作,比如清除掉组件中的定时器和监听的dom事件 destroyed 在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用 作者:善斋书社 链接:https://www.jianshu.com/p/c97415daf180 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

10 获取dom元素在哪个生命周期? 为什么?

created() mounted()

 

11 Created 获取的话怎么获取?




 

12 Vue 混入




 

13 自定义属性




 

14 vue写官网 SEO 优化怎么做?

服务器渲染

 

15 是否做过浏览器兼容




 

16 Sass有几种循环




 

17 独自开发过项目吗?




 

18 响应式的项目介绍?




 

19 Vue 做动态路由




 

双向数据绑定原理

双向数据绑定利用的 Object.defineProperty, 这个方法提供了三个参数 最后对象参数里面有两个函数 一个set函数 set函数 当数据修改的时候自动触发 ,我们在set函数里面 更新视图 一个get函数 get函数当我们调用这个属性的时候触发, get里面必须要有返回值,返回值应该是设置新值,返回值会把数据设置到对象 所以利用这个两个函数 可以进行双向数据绑定 遍历对象 进行递归 Object.defineProperty只能对对向操作,不能操作数组 ,数据利用生生方法 push,unshift ...

 

跨域

跨域源于同源策略 -- 相同的协议 端口号 和 域名 -- 浏览器 (并不包含服务器) 开发的时候 localhost:8080 -- localhost:3000 1 cors 后端给你设置响应头 允许你访问 (一般) 2 webpack 配置代理 比较多 proxy :{} 打包之后不好使 -- localhost:8087/user proxy: { '/api': { // /api 的意义在于,声明axios中url已/api开头的请求都适用于该规则, // 注意是以/api开头,即:axios.post({url: '/api/xxx/xxx'}) target: 'http://127.0.0.1:8087', // 此处target的意义在于:造成跨域是因为访 // 问的host与我们的请求头里的origin不一致,所以我们要设置成一致,这个具体请看下文 changeOrigin: true, pathRewrite: {'^/api': ''} // 此处是大部分文章都不会明说的的地方, // 既然我们设置了代理,则所有请求url都已写成/api/xxx/xxx,那请求如何知道我们到底请求的是哪个服务器的数据呢 // 因此这里的意义在于, 以 /api开头的url请求,代理都会知道实际上应该请求那里, // ‘我是服务器/api’,后面的/api根据实际请求地址决定,即我的请求url:/api/test/test,被代理后请求的则是 // https://我是服务器/api/test/test } } 3 nginx 反向代理 4 jsonp (jsonp使用不多,必须get请求) 利用src属性不不属于同源策略,所以可通过 动态创建script标签,通过script的src属性向服务器发送请求.请求过程中需要携带函数名,服务器接受到参数,获取函数名 会返回对象函数名调用的函数字符串 , 实参就是要传递的数据, 页面需要动态创建函数,形参就在后端接受的到数据 JSONP通过同源策略涉及不到的"漏洞",也就是像img中的src,link标签的href,script的src都没有被同源策略限制到 JSONP只能get请求

 

Post请求

post 带参数 跟跨域有关系 axios 会先发一个 options请求 -- 后端没有处理 -- post请求发送不出来 axios默认格式 application/json axios发送post请求的时候 你转 application/x-www-form-urlencode 问你? post请求 在跨域的时候 传参 会发几次请求? 1 options 2 post 3 前端需要 设置content-type application/x-www-form-urlencode qs qs.tringify(data) import qs from "qs" 1) axios.default.post["Content-Type"] = "application/x-www-from-urlencoded;chaset=utf8" post请求的数据 需要 qs.stringify进行反序列化 data:qs.stringify(data) 请求头里面 一定要会 content-type -------------------------------------------------------------------------- 1 post请求参数要以后端定义好的参数格式去传递 怎么修改格式 axios({ headers:{ "Content-Type":"application/json" // 传递的就是对象 {} 后端接收就是 {} : "x-www-form-urlencoded", // name=zzz&password=admin123 : "form-data" 上传必须这个格式 } }) 2 post请求常见格式 "application/json" // axios默认格式 // 传递的就是对象 {} 后端接收就是 {} : "x-www-form-urlencoded", // name=zzz&password=admin123 : "form-data" 上传必须这个格式 post请求如果带参数会发送几次请求 3 如果后端进行响应头设置跨域 前端发送 post请求(带参数) --- 会先发送 options请求 post请求不带参数 可以直接返回就结果 4 options 跨域检验 需要显检验你传递的参数 -- 参数的格式有问题 application/json 这个格式不合法 options不合法 // optiosn认可的格式 x-www-form-urlencoded form-data text/plain

 

diff算法

逐层比较 在React中即比较两个虚拟DOM节点,当两个节点不同时,应该如何处理。这分为两种情况:(1)节点类型不同 ,(2)节点类型相同,但是属性不同。 不同类型节点的比较 如果发现新旧两个节点类型不同时,Diff算法会直接删除旧的节点及其子节点并插入新的节点,这是由于前面提出的不同组件产生的DOM结构一般是不同的,所以可以不用浪费时间去比较。注意的是,删除节点意味着彻底销毁该节点,并不会将该节点去与后面的节点相比较。 相同类型节点的比较 若是两个节点类型相同时,Diff算法会更新节点的属性实现转换 列表节点的比较 列表节点的操作一般包括添加、删除和排序,列表节点需要我们给它一个key才能进行高效的比较。 diff算法就是数据改变时会创建一个虚拟dom然后去和之前真实的dom进行比较,只改变改变部分渲染为真实的dom,不改变的部分不重新渲染

 

虚拟dom

就是为了优化性能提出来的,通过虚拟dom中的diff算法来判断上一个虚拟dom和现在的虚拟dom之间是否发生改变,如果改变就渲染到真实dom上 在传统的 Web 应用中,我们往往会把数据的变化实时地更新到用户界面中,于是每次数据的微小变动都会引起 DOM 树的重新渲染。 虚拟DOM的目的是将所有操作累加起来,统计计算出所有的变化后,统一更新一次DOM。 这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查,这样一来查找 js 对象的属性变化要比查询 dom 树的性能开销小。 虚拟DOM是在DOM的基础上建立了一个抽象层,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中。 在React中,render执行的结果得到的并不是真正的DOM节点,而仅仅是JavaScript对象,称之为虚拟DOM。

 

面试总结

33 当你输入网址的时候经历了什么?** 1、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。      浏览器缓存可以根据是否需要向服务器重新发起HTTP请求分为两个部分,第一种是强制缓存,第二种是协商缓存 。        强制缓存的优先级高于协商缓存,   所以,首先浏览器要查找当前URL是否存在强制缓存中,   如果不存在的话,会向服务器发送请求,并将请求结果存入缓存中;   如果强制缓存中存在的话,判断HTTP请求头cache-control中的max-age的时间是否过期,   没过期的话,直接使用缓存内容,返回状态码200;   过期了的话,需要用到协商缓存,   通过Etag(资源的实体标识(哈希字符串))来判断资源内容是否更新,更新的话,Etag会改变,服务器根据If-None-Match(是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值)中携带的上次请求返回的Etag值,判断资源内容是否更新,并发送不同的状态码,如果内容更新的话,返回状态码200,重新向服务器发送请求,返回新资源;如果没更新的话,返回304,读取本地缓存。      2、向服务器发送请求,首先需要DNS域名解析   这个过程其实就是将域名还原为IP地址的过程。   当我们在地址栏直接输入的话, 首先浏览器先检查本地hosts文件是否有这个网址映射关系,如果有就调用这个IP地址映射,完成域名解析。   如果没找到则会查找本地DNS解析器缓存,如果查找到则返回。   如果还是没有找到则会查找本地DNS服务器,按照根域服务器(先查询cn域的服务器) ->顶级域,.cn->第二层域,hb.cn ->子域,www.hb.cn的顺序找到IP地址。      3、根据IP建立TCP连接(三次握手)。 第一次握手: 建立连接时,浏览器首先向服务器发送一段报文,表示请求建立新的连接,等待服务器确认;   第二次握手: 服务器收到报文后,确认浏览器的报文Seq序号有效,服务器能正常接收浏览器发送的数据,并同意创建新连接;   第三次握手:浏览器收到服务器发送的确认收到数据的TCP报文后,再向服务器发送确认的报文,这个报文发送完毕,表示浏览器和服务器连接成功,完成三次握手。   4、完成三次握手后,浏览器向服务器发送HTTP请求。 完整的HTTP请求包含请求起始行、请求头部、请求主体三部分。   5、服务器处理请求,浏览器接收HTTP响应。   6、根据请求的结果渲染页面,构建DOM树。    这是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: 重排和重绘。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为重排;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为重绘。   7、关闭TCP连接(四次挥手)。 第一次挥手是浏览器发完数据后,发送一段请求断开连接的报文(FIN)。   第二次挥手是服务器发送一个表示同意断开的报文(ACK),   第三次挥手是服务器发送一段请求断开连接的报文(FIN)。      第四次挥手是浏览器发送一个表示同意断开的报文(ACK)      服务端更新图片之后,在前端显示图片不更新 在服务端的图片更新之后,前端的图片没有更新? 这是因为浏览器首次读取服务端的图片之后,再次读取同名图片,会直接从临时文件中读取,不再请求服务端。如果清除浏览器缓存,则图片更新。 可以修改图片名,或者给图片src后加上随机数。 var version = Math.random(); < img src="./test.png?"+version /> 原理: 由于在img的src中增加了随机数参数,多次访问图片时,浏览器认为是访问了不同的图片路径(或者说是访问了不同的图片),浏览器会每次重新访问服务器读取图片, 而不再读取缓存中的图片。   

 

虚拟DOM

虚拟 dom 是相对于浏览器所渲染出来的真实 dom而言的,在react,vue等技术出现之前,我们要改变页面展示的内容时只能遍历整颗 dom 树,找到需要修改的 dom 然后修改样式行为或者结构。 这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查,这样一来查找 js 对象的属性变化要比查询 dom 树的性能开销小。 react以及Vue在diff时,都是在对比虚拟dom节点,下文提到的节点都指虚拟节点

 

setState(updater, [callback]) 有第二个参数是就会变成同步,类组件

 




 


 

猜你喜欢

转载自blog.csdn.net/m0_61043829/article/details/130594297