前端面试0

1、JavaScript

1.1、基本数据类型(7种)

1、number
js不区分小数和整数

123//整数
123.1 //浮点数
1.123e3 //科学计数法
-9 //负数
NaN //Not a number   isNaN()判断是否为NaN
Infinity //表示无限大

2、字符串

‘abc’ “abc”

3、布尔值

true,false

4、null和undefined

  • null 空
  • undefined 未定义

5、数组

一系列相同类型的对象

var arr = [1,2,3,4,'string',true];

new Array(1,2,4,5,'hello');

去数组下标:如果越界就会undefined

6、对象

对象是大括号,数组是中括号

var person = {
	name: "zhouyi",
    age: 4,
    tags: ['js','java','web','...']
}

取对象的值

person.age
> 4
person.name
> 'zhouyi'
person.tags
> (4) ['js', 'java', 'web', '...']

1.2、this的指向(new,隐式绑定,显式绑定)

this默认绑定我们可以理解为函数调用时无任何调用前缀的情景,它无法应对我们后面要介绍的另外四种情况,所以称之为默认绑定,默认绑定时this指向全局对象(非严格模式)

默认绑定:这条规则是最常见的,也是默认的。当函数被单独定义和调用的时候,应用的规则就是绑定全局变量window(严格模式下是undefined)。即没有其他绑定规则存在时的默认规则

NEW绑定准确来说,js中的构造函数只是使用``new 调用的普通函数,它并不是一个类,最终返回的对象也不是一个实例,只是为了便于理解习惯这么说罢了。

​ 1.以构造器的prototype属性为原型,创建新对象;

​ 2.将this(可以理解为上句创建的新对象)和调用参数传给构造器,执行;

​ 3.如果构造器没有手动返回对象,则返回第一步创建的对象

隐式绑定,如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上。如果函数调用前存在多个对象,this指向距离调用自己最近的对象

显式绑定是指我们通过call、apply以及bind方法改变this的行为,相比隐式绑定,我们能清楚的感知 ``this 指向变化过程。

1.3、Function的call, apply, bind方法

call

调用一个对象的一个方法,以另一个对象替换当前对象。

function Animal(name){   
  this.name=name;   
  this.showName=function(){   
    console.log(this.name);   
  }   
}   
function Dog(name){   
  Animal.call(this.name);   
}   
var dog=new Dog("Crazy dog");   
dog.showName();

输出:Crazy dog

Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么Dog就能直接调用Animal的所有属性和方法。

apply

应用某一对象的一个方法,用另一个对象替换当前对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSBfWjVg-1657884268102)(file://C:\Users\chow\AppData\Roaming\Typora\typora-user-images\image-20211213152034290.png?lastModify=1639723017)]

bind

bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

注意:bind方法的返回值是函数

总结

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
  • apply 、 call 、bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

1.4、Promise, eventloop(事件循环),宏任务和微任务

JS引擎常驻于内存中,等待宿主将JS代码或函数传递给它。
也就是等待宿主环境分配宏观任务,反复等待 - 执行即为事件循环。

1、执行栈选择最先进入队列的宏任务(一般都是script),执行其同步代码直至结束;

2、检查是否存在微任务,有则会执行至微任务队列为空;

3、如果宿主为浏览器,可能会渲染页面;

4、开始下一轮tick,执行宏任务中的异步代码(setTimeout等回调)

遇到宏任务先执行宏任务,再看eventQueue里面有没有微任务,执行

1.5、闭包(概念,用途,手写)

闭包的作用:隐藏变量,避免全局污染;可以读取函数内部的变量。

闭包的概念: 有一个A函数,在A函数内部返回一个B函数;在A函数外部有变量引用这个B函数;B函数内部访问着A函数内部的私有变量。(核心就是利用执行空间不销毁的原理)、

for(var i=0;i<10;i++){
    ~function(){
        setTimeout(()=>{
            console.log(i);//10次10 获得执行次数
        },1000)
    }(i);
}

for(let i=0;i<10;i++){
    ~function(){
        setTimeout(()=>{
            console.log(i);//0~9 获得每一个i
        },1000)
    }(i);
}

1.6、原型链

__ proto __:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iF0sEHyg-1657884268103)(file://C:\Users\chow\AppData\Roaming\Typora\typora-user-images\image-20211213161448887.png?lastModify=1639724451)]

1.7、继承(extends,原型链继承,构造函数继承,组合继承,寄生组合继承)

原型链继承

重点:让新实例的原型等于父类的实例。
特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)、

缺点:1、新实例无法向父类构造函数传参。
2、继承单一。
3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

本质:查看对象原型

构造函数继承

重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))
    特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
       2、解决了原型链继承缺点1、2、3。
       3、可以继承多个构造函数属性(call多个)。
       4、在子实例中可向父实例传参。
    缺点:1、只能继承父类构造函数的属性。
       2、无法实现构造函数的复用。(每次用每次都要重新调用)
       3、每个新实例都有父类构造函数的副本,臃肿。

组合继承**:组合原型链和构造函数

重点:结合了两种模式的优点,传参和复用
    特点:1、可以继承父类原型上的属性,可以传参,可复用。
       2、每个新实例引入的构造函数属性是私有的。
    缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

寄生组合继承

寄生组合式继承(常用)
    寄生:在函数内返回对象然后调用
    组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参

1.8、深拷贝和浅拷贝

​ 深拷贝浅拷贝只针对对象和数组这种引用数据类型。

​ 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

1.9、事件冒泡/捕获,事件委托,阻止冒泡,哪些事件不能冒泡

1、一个完整的JS事件流是从window开始,最后回到window的一个过程
  2、事件流被分为三个阶段(15)捕获过程、(56)目标过程、(6~10)冒泡过程

取消冒泡:

标准的W3C 方式:e.stopPropagation();这里的stopPropagation是标准的事件对象的一个方法,调用即可

非标准的IE方式:ev.cancelBubble=true; 这里的cancelBubble是 IE事件对象的属性,设为true就可以了

事件委托:

把事件交给父级处理。

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;//防止点击到父级时触发事件
var target = ev.target || ev.srcElement;//标准用target ie用srcelement
    if(target.nodeName.toLowerCase() == 'li'){
         alert(123);
         alert(target.innerHTML);
    }
  }
}//效果不同可以用 switch选择

不能冒泡

ul事件:load(加载)、unload(卸载)、scroll(滚动)、resize(大小)

焦点事件:blur(失去焦点)、focus(焦点)

鼠标事件:mouseleave、mouseenter

1.10、sort() 的复杂度

sort函数进行排序的时间复杂度为n*log2n。
原理:不是简单的快排 STL的sort()算法,数据量大时采用Quick Sort,分段递归排序,一旦分段后的数据量小于某个门槛,为避免Quick Sort的递归调用带来过大的额外负荷,就改用Insertion Sort。如果递归层次过深,还会改用Heap Sort。

2.浏览器

2.1、回流和重绘

html 加载时发生了什么

在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等。
浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体
DOM Tree 和样式结构体组合后构建render tree, render tree类似于DOM tree,但区别很大,因为render tree能识别样式,render tree中每个NODE都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到 render tree中。我自己简单的理解就是DOM Tree和我们写的CSS结合在一起之后,渲染出了render tree。

什么是回流

当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。

什么是重绘

当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

区别:

他们的区别很大:
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流
当页面布局和几何属性改变时就需要回流
比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变

2.2、http缓存,协商缓存

HTTP缓存的2个要点就是:

  1. 检查缓存是否过期(强缓存)
  2. 若缓存过期,与服务器协商是否更新缓存(协商缓存)。

而这2点每个都包含相关的2个报文请求首部:

  • 强缓存:过期时间Expires 和有效期Cache-Control: max-age
  • 协商缓存:日期再验证If-Modified-Since和实体标签再验证If-Not-Matched

2.3、cookies, session,Storage, localStorage

cookies:document.cookie(获取cookie)

  • 因为存储在客户端,容易被客户端篡改,使用前需要验证合法性
  • 不要存储敏感数据,比如用户密码,账户余额
  • 使用 httpOnly 在一定程度上提高安全性
  • 尽量减少 cookie 的体积,能存储的数据量不能超过 4kb
  • 设置正确的 domain 和 path,减少数据传输
  • cookie 无法跨域
  • 一个浏览器针对一个网站最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie
  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

2.4、跨域问题

3、CSS

3.1、盒子模型,怪异盒子

1、标准盒模型中width指的是内容区域content的宽度;height指的是内容区域content的高度。

标准盒模型下盒子的大小 = content + border + padding + margin

img

2、怪异盒模型中的width指的是内容、边框、内边距总的宽度(content + border + padding);height指的是内容、边框、内边距总的高度

怪异盒模型下盒子的大小=width(content + border + padding) + margin

img

  • 当设置为box-sizing:content-box时,将采用标准模式解析计算(默认模式);
  • 当设置为box-sizing:border-box时,将采用怪异模式解析计算;

3.2、float,清除浮动

3.2.1标准文档流

3.2.2display

<style>
	/* 
    	block 块元素
    	inline 行内元素
    	inline-block 是块元素,但是可以内联,在一行
    	none 消失
    */
    div{
        width: 120px;
        height: 120px;
        border: 1px solid red;
        display: inline-block;
    }
    span{
        width: 120px;
        height: 120px;
        border: 1px solid red;
        display: inline-block;
    }
</style

1、这个也是一种实现行内元素排列的方式,但是很多情况都使用float

3.2.3、float

浮动的盒子可以向左浮动,也可以向右浮动,知道它的外边缘碰到包含框或者另一个浮动盒子为止

float:right;/*右浮动*/
float:left;/*左浮动*/

3.2.4、父级边框塌陷问题

clear

clear:both/right/left/none;/*清除浮动*/

解决方法

1、增加父级元素的高度

简单,假设元素设有了固定的高度,就会被限制

#father{
    border: 1px #000 solid;
    height: 800px;
}

2、增加一个空的div标签,清除浮动

简单,但是代码中尽量避免空div

.clear{
    clear: both;
    margin: 0;
    padding: 0;
}

3、overflow

简单,下拉的一些场景 避免使用

在父级元素中增加一个 overflow: hidden;

4、父类添加一个伪类 :after

没有副作用,建议使用

#father:after{
    content: '';/*添加一个空标签*/
    display: block;/*将空标签变成块级元素*/
    clear: both;/*设置清除浮动*/
}

3.2.5、对比、

  • display

​ 方向不可控

  • float

​ 浮动起来或脱离标准文档流,要解决父级边框塌陷的问题

3.3、垂直居中的方法

水平居中

  • 行内元素:
    • 块级元素直接给父元素设置 text-align: center;
    • 非块级元素,先把父类设置为块级元素,diiplay:block
  • 块级元素:margin:0 auto;父元素添加属性 display: flex; justify-content: center;

垂直居中

  • 单行的行内元素:只需要设置单行行内元素的"行高等于盒子的高"即可;
  • 多行的行内元素:使用给父元素设置display:table-cell;和vertical-align: middle;
  • 块级元素:父元素添加:display:flex;align-items:center

水平垂直居中

设置父元素为flex定位,justify-content: center; align-items: center;

3.4、flow, absolute, relative, stickyflex定位

相对定位position:relative

相对原来的位置,进行指定的偏移,仍然在文档流中,原来的位置会被保留

固定定位position:absolute

绝对定位position:fixed

固定定位是相对于屏幕而绝对定位的基准则是父级元素

3.5、样式优先级

  • D 选择器, 如 #id{}
  • 类选择器, 如 .class{}
  • 属性选择器, 如 a[href=“segmentfault.com”]{}
  • 伪类选择器, 如 :hover{}
  • 伪元素选择器, 如 ::before{}
  • 标签选择器, 如 span{}
  • 通配选择器, 如 *{}

**CSS 优先规则3:**优先级关系:内联样式 > ID 选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 = 伪元素选择器

4、HTML

4.1、块元素,行内元素

  • 块元素

独占一行
可以设置宽度,高度,margin,padding
宽度默认所在容器的宽度
可以容纳内联元素和块级元素

常见的块级元素:

<caption>	定义表格标题
<address>定义地址
<dd>定义列表中定义条目
<div>定义文档中的分区或节
<dl>定义列表
<dt>定义列表中的项目
<fieldset>定义一个框架集
<form>创建 HTML 表单
<h1>~<h6>定义标题
<hr>定义一条水平线
<p>定义段落
<table>定义表格
<li>标签定义列表项目
<ul>定义无序列表
<ol>定义有序列表
  • 行内元素

常见的特点如下:

与其他行内元素并排
设置宽高无效
默认的宽度就是文本内容的宽度
水平方向的 padding 和 margin 属性可以使用。
只能容纳文本级元素和内联元素
注意:
a 标签可以放块级元素,但是连接里面不能再放连接
常见的行内元素:

<a>	标签定义超链接
<abbr>	表示一缩写形式
<acronym>	定义只取首字母缩写
<b>	定义字体缩写
<bdo>	可覆盖默认的文本方向
<big>	定义大号字体加粗
<br>	定义换行
<code>	定义计算机代码文本
<label>	标签
<select>	创建单选或多选菜单
<span>	组合文档中的行内元素
<small>	定义小号字体

4.2、语义化标签: header, section等

4.3、异步加载JS文件: defer和async

  • defer加载完成后会按照script标签的顺序执行
  • async加载完成后立即执行

5、 Vue

5.1、响应式原理(Vue2和Vue3)

意思就是在改变数据的时候,视图会跟着更新。

VUE则是利用了Object.defineProperty的方法里面的setter 与getter方法的观察者模式来实现。

  • 第一步:组件初始化的时候,先给每一个Data属性都注册getter,setter,也就是reactive化。然后再new 一个自己的Watcher对象,此时watcher会立即调用组件的render函数去生成虚拟DOM。在调用render的时候,就会需要用到data的属性值,此时会触发getter函数,将当前的Watcher函数注册进sub里。
  • 第二步:当data属性发生改变之后,就会遍历sub里所有的watcher对象,通知它们去重新渲染组件。

5.2、生命周期,父子生命周期的顺序

生命周期

1、生命周期:vue从创建vue实例到组件销毁的过程 自动创建的函数

​ 每个Vue实例在被创建时都要经过一系列的初始化过程——例如:需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数

2、生命周期函数:(与data(){} 同级)

  • beforeCreate new vue实例后,创建之前 ——获取不到data methods 和数据
  • created *** 创建之后,可以实现网络请求
  • beforeMount 挂载之前,render首次被调用
  • mounted *** 挂载完毕 ——初次获取DOM元素的地方
  • beforeUpdate 更新之前,数据更新了,视图未更新
  • updated *** 更新之后,数据和视图 同步
  • beforeDestroy 销毁之前,什么都可以做
  • destroyed 销毁之后,清空数据 或者 计时器 、监听器、子实例等
  • activated keep-alive组件激活时调用
  • deactivated keep-alive组件停用时调用

父子生命周期的顺序

  • 加载渲染过程
  父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
  • 子组件更新过程
  父beforeUpdate->子beforeUpdate->子updated->父updated
  • 父组件更新过程
  父beforeUpdate->父updated
  • 销毁过程
  父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

5.3、组件通信: props, $emit等

prop数据传递——父传子

实现组件之间数据传递——父传子

父组件:parent

<Son msg='hello parent' :num='100' :aa='info'/>
data(){
	return{
		num:'200,
		info:'im parent'
	}
}

子组件:Son

<p>
    接收父组件传递过来的数据msg:{{ msg }} num:{{ num }} aa:{{ aa }}
</p>
props:['msg','num','aa']//方式一,使用数组接收
props:{msg:String,num:[String,Number],aa:{type:String,default:'默认值'},propC:{type:String,required:true//必填, arr:{type:Array,//typr:Object//对象或数组默认值必须从一个工厂函数获取 default:function(){return []}}}

$emit自定义事件——子传父

//子组件
<div>
    <h2>son1子组件</h2>
    <button @click="sendData">向父组件发送数据</button>
    <h2>父组件传递过来的num:{{ num }}</h2>
    <button @click="addNum">自定义事件,让父组件完成对num的运算</button>
    <!-- 接收父组件传递过来的函数实现对父组件中的num的运算 -->
    <button @click="fun()">使用父组件传递过来的函数方式一:直接使用</button>
    <button @click="addNum1()">使用父组件传递过来的函数方式二:自己的函数来调用</button>
  </div>
<script>
export default {
  props:{
    num:Number,
    fun:Function
  },
  data(){
    return {
      Data:'Son1发给父组件'
    }
  },
  methods:{
    sendData(){
      //自定义事件--抛出一个自定义事件
      this.$emit('getData',this.Data)
    },
    addNum(){
      this.$emit('addNum')
    },
    addNum1(){
      this.fun()
    }
  }
}
</script>

//父组件
<div>
    <Son1 @getData='getData' :num='num' @addNum='addNum' :fun='addNum'></Son1>
</div>
<script>
export default {
  components:{
    Son,
    Son1
  },
  data(){
    return{
      num:200,
    }
  },
  methods:{
    getData(val){
      console.log(val);
      this.msg = val
    },
    addNum(){
      this.num ++;
    }
  }
}
</script>

5.4、Vuex: action和mutation

5.5、diff原理

5.6、v-if 和v-show

3、v-show=’ 表达式 ’

  • 是否显示 true显示 false隐藏
  • 控制css属性:display: block/ none

4、v-if=’ ’

  • 是否显示 true显示 false隐藏
  • 控制元素的创建和销毁

5.7、data为什么是一个函数

1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。

2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。

3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。

4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果

5.8、computed 和watch

computed(计算属性)

处理数据后把数据缓存起来,使用数据的时候直接使用缓存中的数据,但如果原数据被修改,需要重新计算

<temlate>
	<div>
        <p>字符串取反,函数封装:{{ qufan() }}</p>
        <p> 字符取反,计算属性:{{ msg2 }}</p>
    </div>
</temlate>
<script>
export default {
    data(){
        return{
            msg:'hello world'
        }
    },
    methods:{
        qufan(){return this.msg.split(''),reverse().join('');}
    },
    computed:{
        msg2(){return this.msg.split(''),reverse().join('');}
    }
}
</script>

watch侦听器

vue通过watch现象提供了一个更通用的方法,来响应数据的变化

<div>
    <h2>watch 侦听器</h2>
    <input type="text" v-model="inp">
</div>
<script>
 watch:{
    inp:function(n,o){//n:new;o:old
      console.log(n,o);
    }
  }
</script>

区别

相同点:计算属性和侦听器都是观察页面的数据变化

不同点:

  • computed:是计算属性,依赖其他属性值
    • 只支持缓存,只有数据发生变化时才会重新计算
    • 不支持异步,当computed内有异步操作时无效
  • watch:没有缓存性,更多的是观察的作用,类似于数据的监听回调,当监听的数据变化时都会执行回调进行后去操作
    • 不支持缓存,数据变化直接触发相应的操作
    • 支持异步
    • 监听的函数接受两个参数,第一个参数是最新的值;第二个参数是输入之前的值;当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听

5.9、mixin mixin的缺陷

5.10、异步组件, keep-alive

异步组件

1、说明:使用组件的时候再去加载这个组件,提高代码执行速度

1、默认引入组件:

​ 提前加载组件

import ComA from './ComA.vue';

3、一部组件写法:——局部

  • const ComA = ()=>import’./ComA.vue’)

  • <script>
    export default{
        components:{
            ComA,
            ComB,
            ComA = ()=>import'./ComA.vue')
            ComB = ()=>import'./ComB.vue')
        }
    }
    </script>
    

动态组件:keep-alive

1、作用:实现组建的动态切换 选择加载哪个组件

2、语法:

<component :is='加载的组件名'></component>

3、特点:

​ 通过组件的销毁和重建过程实现组件的切换

4、在动态组件上使用keep-alive——使组件失活

<keep-alive>
	<component :is='加载的组件名称'></component>
</keep-alive>

<!--include and exclude-->
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

<!-- max:最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。-->
<keep-alive :max="10">
  <component :is="view"></component>
</keep-alive>

5.11、路由,history模式

6.前端工程化

6.1、bebal原理

6.2、模块化方案: ES6和commonJS

7、计算机网络

7.1、http: 数据包的构成,状态码, http2和http3,https

http: 数据包的构成

HTTP请求包(GET、POST等请求方法)由三个部分构成,分别是:方法-URI-协议/版本,请求头,请求正文

HTTP应答包和HTTP请求包相似,由三个部分构成,分别是:协议-状态代码-描述,应答头,应答正文

状态码

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误

http缓存

7.2、tcp和udp,tcp握手和挥手

传输控制协议TCP

  • 面向连接的、可靠的、基于字节流的传输层通信协议
  • 将应用层的数据流分割成报文段并发送给目标节点的TCP层
  • 数据包都有序号,对方收到则发送ACK确认,未收到则重传
  • 使用校验和来校验数据在传输过程中是否有误

UPD的特点

  1. 面向非连接
  2. 不维护连接状态,支持同时向多个客户端传输相同的消息
  3. 数据包头只有8个字节,额外开销较小
  4. 吞吐量只受限于数据生成速率、传输速率以及及其性能
  5. 尽最大努力交付,不保证可靠交付,不需要维持复杂的链接状态表
  6. 面向报文,不对应用程序提交的报文信息进行拆分或者合并

三次握手:

  • 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN。此时客户端处于 SYN_SENT 状态。( 首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。 )
  • 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD 的状态。 ( 在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。 )
  • 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接。 ( 确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。

四次挥手:

  1. 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
  2. 第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
  3. 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
  4. 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。

7.3、OSI参考模型

7.4、get和post的区别

标准区别

GET在浏览器回退时是无害的,而POST会再次提交请求。

GET产生的URL地址可以被Bookmark,而POST不可以。

GET请求会被浏览器主动cache,而POST不会,除非手动设置。

GET请求只能进行url编码,而POST支持多种编码方式。

GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

GET请求在URL中传送的参数是有长度限制的,而POST么有。

对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

GET参数通过URL传递,POST放在Request body中。

区别

GETPOST
点击返回/刷新按钮没有影响数据会重新发送(浏览器将会提示用户“数据被从新提交”)
添加书签(bookmark)可以不可以
缓存可以不可以
编码类型(Encoding type)application/x-www-form-urlencodedapplication/x-www-form-urlencoded or multipart/form-data. 请为二进制数据使用multipart编码
历史记录没有
长度限制没有
数据类型限制只允许ASCII字符类型没有限制。允许二进制数据
安全性查询字符串会显示在地址栏的URL中,不安全,请不要使用GET请求提交敏感数据因为数据不会显示在地址栏中,也不会缓存下来或保存在浏览记录中,所以看POST求情比GET请求安全,但也不是最安全的方式。如需要传送敏感数据,请使用加密方式传输
可见性查询字符串显示在地址栏的URL中,可见查询字符串不会显示在地址栏中,不可见

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

1. GET与POST都有自己的语义,不能随便混用。
2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

8.手写代码

8.1、事件委托

8.2、promise的all()和race()

8.3、数组的call(), apply(), bind()

8.4、实现new方法

8.5、防抖和节流

8.6、快排,冒泡排序

冒泡排序

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。 [1]
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

8.7、二分查找,二分插入

8.8、数组去重

8.9、深拷贝

8.10、深度/广度优先遍历

8.11、正则表达式.

8.12、复杂度分析

  • vue.js能解决什么问题

​ Vue.js 是开源的一个前端开发库,通过简洁的 API 提供高效的数据绑定和灵活的组件系统

vue生命周期

vue每个组件都是独立的,每个组件都有一个属于它的生命周期,从一个组件创建、数据初始化、挂载、更新、销毁

v-if和v-show的区别

​ v-if控制节点是否存在,有一个局部编译或者卸载的过程;v-show是调整display的none和block。如果需要非常频繁地切换,使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好

  • 组件通讯

​ 组件是一个独立的整体,将组件拼接起来,建立联系就是组件通讯

​ 父子组件通讯:使用props

  • 数据双向绑定

​ 当Model变化时,View-Model会自动更新,View也会自动变化。很好的做到数据的一致性

  • mvvm和mvc的区别

    mvvm:model(数据模型,指后端进行的业务逻辑处理和数据操控,主要是数据库)-view(视图层,用HTML和CSS构建,展现VIewModel的数据)-viewModel(视图数据层,对数据进行二次封装,包含视图的状态和行为)

    mvc:model-view-Controller(控制器作用于模型和视图上。它控制数据流模型对象,并在数据变化时更新视图。它使视图与模型分离开)

​ MVVM主要解决了MVC中大量的DOM操作使页面渲染性能降低,加载速度变慢,影响用户体验

  • 自动化测试
  • 数据类型

​ number、string、boolean、undefined、null(object)、对象和数组

=:==值等、===值等类型等

深拷贝和浅拷贝的区别、思路

​ 深拷贝浅拷贝只针对对象和数组这种引用数据类型。

​ 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

原型、构造函数和实例的理解

​ 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型对象的指针。

​ 构造函数:是用来创建对象的函数,本质上也是函数,通过new操作符来调用的就是构造函数

​ 实例:通过new操作符调用了函数Person,并且生成了person1,这个person1就是person函数对象的一个实例

​ 原型对象:当我们每次创建一个函数的时候,函数对象都会有一个prototype属性,这个属性是一个指针,指向它的原型对象

闭包解决了什么问题、导致什么问题

​ 闭包:通过闭包可以在函数外部能访问到函数内部的变量

​ 原理:Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包

​ 作用:隐藏变量,避免全局污染;可以读取函数内部的变量

​ 缺点:会导致内存占用过多,闭包将函数的活动对象维持在内存中。闭包只能取得外部函数中任何变量的最后一个值,在使用循环且返回的函数中带有循环变量时会得到错误结果;当返回的函数为匿名函数时,注意匿名函数中的this指的是window对象

this

默认绑定:这条规则是最常见的,也是默认的。当函数被单独定义和调用的时候,应用的规则就是绑定全局变量window(严格模式下是undefined)。即没有其他绑定规则存在时的默认规则

NEW绑定准确来说,js中的构造函数只是使用``new 调用的普通函数,它并不是一个类,最终返回的对象也不是一个实例,只是为了便于理解习惯这么说罢了。

​ 1.以构造器的prototype属性为原型,创建新对象;

​ 2.将this(可以理解为上句创建的新对象)和调用参数传给构造器,执行;

​ 3.如果构造器没有手动返回对象,则返回第一步创建的对象

隐式绑定,如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上。如果函数调用前存在多个对象,this指向距离调用自己最近的对象

显式绑定是指我们通过call、apply以及bind方法改变this的行为,相比隐式绑定,我们能清楚的感知 ``this 指向变化过程。

跨域问题

p和div的区别

​ 首先第一个区别:语义。p标签的语言是段落(paragraph),而div是没有语义的,只是一块用来方便设置样式排版的。

第二个区别:就是p标签有默认样式,段落前后都会有一行空白区域,当然你用div自己设置也是可以的。div的添加如果没有什么css修改的话对样式没有影响

盒子模型

​ 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用。CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。

Margin(外边距) - 清除边框外的区域,外边距是透明的。

Border(边框) - 围绕在内边距和内容外的边框。

Padding(内边距) - 清除内容周围的区域,内边距是透明的。

Content(内容) - 盒子的内容,显示文本和图像

  • 水平垂直居中一个页面元素

​ 设置父元素为相对定位,给子元素设置绝对定位,top: 0; right: 0; bottom: 0; left: 0; margin: auto;

​ 设置父元素为相对定位,给子元素设置绝对定位,left: 50%; top: 50%; margin-left: --元素宽度的一半px; margin-top: --元素高度的一半px;

left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%);

​ 设置父元素为flex定位,display:flex;justify-content: center; align-items: center;

  • 清除浮动、区别

清除浮动主要是为了解决,父元素因为子级元素浮动引起的内部高度为0的问题

​ 父元素添加overflow:hidden(优点:代码简洁

缺点:内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素)

  • 重绘回流

什么是回流

当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。

什么是重绘

当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

区别:

他们的区别很大:
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流
当页面布局和几何属性改变时就需要回流
比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变

  • 响应式布局、方法

  • css框架

从输入url到页面显示发生了什么

在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等。
浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体
DOM Tree 和样式结构体组合后构建render tree, render tree类似于DOM tree,但区别很大,因为render tree能识别样式,render tree中每个NODE都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到 render tree中。我自己简单的理解就是DOM Tree和我们写的CSS结合在一起之后,渲染出了render tree。

web前端优化的策略:

减少请求、

压缩内容比如图片之类的、

将js文件内容最小化,去掉重复的脚本,去掉空白字符、注释、最小化变量名

减少外部脚本的使用,减少dns查询时间

将css和js文件放在独立的外部文件中引用

避免重定向的发生,通过配置apache的alias或使用mod_rewrite模块等方法,避免不必要的重定向。

== 和 ===

你什么情况下会用===

闭包的应用场景

怎么用css画一个三角形

Let和var的区别

  • var是函数作用域,let是块作用域。
  • let不能在定义之前访问该变量,但是var可以。
  • let不能被重新定义,但是var是可以的

webpack的作用是什么

  • 进行重新加载编译。实际就是将浏览器不认识的语法编译成浏览器认识的语法。比如less
    编译成css,ES6 语法 转成 ES5等等。
  • 减少io请求。通常我们在请求后,会返回一个html到浏览器。这时,我们如果打开控制台,就会发现在html页面通过script,link等标签引用的静态资源, 浏览器会再次发出请求去获取这些资源。但是webpack的打包,将所有的静态资源都合并好了,减少了io请求。

Vue和react的区别

React为什么比vue效率高

什么时候需要用vuex

为什么说vue是轻量级的框架

vue中直接写this. xxx是怎么更新UI界面的?(数据绑定原理)

js怎么实现继承

为什么会出现TypeScript

Promise用法,promise.all

后端知识了解哪些?

你使用node搭建过简单的服务器吗?

session是如何确定用户身份的?购物车商品能否存在cookie中,为什么?

为什么promise通常和Async、await和起来用

Async、await运行的时候会解析成什么样来运行

为什么node的api通常会设计成自己传入回调函数的形式

现场做了几题有关闭包和宏任务、微任务的输出相关的题目

//字符串'123456' 翻转成'654321'

function reverse(s){

var arr = '' for(var i = s.length-1;i>0;i--){

str += s[i] return str

    }

}

var str = '123456'

str = reverse(str)

document.write(str)

var arr = [10,24,23,11,16,45,82,94,12]; // 遍历数组

for (var i = 0; i < arr.length - 1; i++) { // 这里要根据外层for循环的 i ,逐渐减少内层 for 循环的次数

for (var j = 0; j < arr.length - 1 - i; j++) {

if (arr[j] > arr[j + 1]) {

var num = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = num;

        }

    }

}

document.write(arr)//10,11,12,16,23,24,45,82,94

http状态码

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误

http缓存

浏览器同源策略

js继承的方法

  • 原型链继承
  • 构造继承
  • 实例继承
  • 拷贝继承
  • 组合继承
  • 寄生组合继承

判断是数组的方法

Array.isArray(variable)

浏览器输入url到页面渲染
深拷贝

var targetObj = JSON.parse(JSON.stringify(copyObj))
let arr4 = JSON.parse(JSON.stringify(arr))

function deepCopy( source ) {
if (!isObject(source)) return source; //如果不是对象的话直接返回
    let target = Array.isArray( source ) ? [] : {} //数组兼容
    for ( var k in source ) {
    	if (source.hasOwnProperty(k)) {
    		if ( typeof source[ k ] === 'object' ) {
            	target[ k ] = deepCopy( source[ k ] )
        	} else {
            	target[ k ] = source[ k ]
        	}
    	}
    }
    return target
}

function isObject(obj) {
    return typeof obj === 'object' && obj !== null
}

css旋转

transform:rotate(240deg);

css不会继承的属性

1、display:规定元素应该生成的框的类型

2、文本属性:
vertical-align:垂直文本对齐text-decoration:规定添加到文本的装饰
text-shadow:文本阴影效果white-space:空白符的处理unicode-bidi:设置文本的方向

3、盒子模型的属性:width、height、margin 、margin-top、margin-right、margin-bottom、margin-left、border、border-style、border-top-style、border-right-style、border-bottom-style、border-left-style、border-width、border-top-width、border-right-right、border-bottom-width、border-left-width、border-color、border-top-color、border-right-color、border-bottom-color、border-left-color、border-top、border-right、border-bottom、border-left、padding、padding-top、padding-right、padding-bottom、padding-left

4、背景属性:background、background-color、background-image、background-repeat、background-position、background-attachment

5、定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index

6、生成内容属性:content、counter-reset、counter-increment

7、轮廓样式属性:outline-style、outline-width、outline-color、outline

8、页面样式属性:size、page-break-before、page-break-after

9、声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during

清除浮动
性能优化
跨域
css实现三角形时加宽高后的宽高
flex布局

flex-direction:row(默认值主轴为水平方向,起点在左端。)row-reverse(主轴为水平方向,起点在右端)column(主轴为垂直方向,起点在上沿。)column-reverse(主轴为垂直方向,起点在下沿。)
flex-wrap:nowrap(默认):不换行。wrap:换行,第一行在上方。wrap-reverse:换行,第一行在下方。
justify-content:flex-start(默认值):左对齐;flex-end:右对齐;center: 居中;space-between:两端对齐,项目之间的间隔都相等。;space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

https://www.runoob.com/w3cnote/flex-grammar.html

vue响应式原理
虚拟dom
为什么选择vue
es6常用语法及应用
promise原理及方法
题目:找出数组中出现过一次的元素

function duplicates(arr) {
    var result = [];
    arr.forEach(function(item){
        if(arr.indexOf(item)!=arr.lastIndexOf(item)&&result.indexOf(item)==-1)
            result.push(item);
    })
    return result;
}

前端性能优化(方法及原理)

vue生命周期、beforecrated和created的区别

beforemounted和mounted的区别、beforeupdate和update的区别、computed和watch的区别

computed方法里修改input的值怎么写

watch只能监视一个值吗

promise运用场景、写定时器

https://www.kuangstudy.com/bbs/1363787177883869185
background-position、background-attachment

5、定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index

6、生成内容属性:content、counter-reset、counter-increment

7、轮廓样式属性:outline-style、outline-width、outline-color、outline

8、页面样式属性:size、page-break-before、page-break-after

9、声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during




 清除浮动 
 性能优化 
 跨域 
 css实现三角形时加宽高后的宽高 
 flex布局 

```css
flex-direction:row(默认值主轴为水平方向,起点在左端。)row-reverse(主轴为水平方向,起点在右端)column(主轴为垂直方向,起点在上沿。)column-reverse(主轴为垂直方向,起点在下沿。)
flex-wrap:nowrap(默认):不换行。wrap:换行,第一行在上方。wrap-reverse:换行,第一行在下方。
justify-content:flex-start(默认值):左对齐;flex-end:右对齐;center: 居中;space-between:两端对齐,项目之间的间隔都相等。;space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

https://www.runoob.com/w3cnote/flex-grammar.html

vue响应式原理
虚拟dom
为什么选择vue
es6常用语法及应用
promise原理及方法
题目:找出数组中出现过一次的元素

function duplicates(arr) {
    var result = [];
    arr.forEach(function(item){
        if(arr.indexOf(item)!=arr.lastIndexOf(item)&&result.indexOf(item)==-1)
            result.push(item);
    })
    return result;
}

前端性能优化(方法及原理)

vue生命周期、beforecrated和created的区别

beforemounted和mounted的区别、beforeupdate和update的区别、computed和watch的区别

computed方法里修改input的值怎么写

watch只能监视一个值吗

promise运用场景、写定时器

https://www.kuangstudy.com/bbs/1363787177883869185

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值