所有题总结*82

八股文

  1. 数据类型var、const、let 对比:click
const:定义常量,不可以被修改(如果声明的是复合类型可以修改),必须被初始化,形成块级作用域。
var:定义变量可以修改,不初始化为undefined,不会报错。会挂载到weindow上,存在变量提升,同一作用域下能声明同名变量,以上三特性仅var适用。
let:块级作用域,函数内部使用let定义,对函数外部没有影响。在声明之前调用存在暂存死区(会输出 error:a is not defined)。
  1. 你怎样看待闭包 click
  2. 柯里化 :click
实现一个函数add,能够计算
add(1)(2)(3) = 6
add(1,2,3)(4) = 10
add(1)(2)(3)(4)(5) = 15

 function add(){
 	//第一次执行add的时候执行这里
 	let args = Array.prptotype.slice.call( arguments );
 	//在传入第 2-n 个参数的时候才执行iner函数;第一次执行add的时候定义
 	let inner = function(){
 		args.push(...arguments);
 		return inner;
 	}
 	//之后console.log的时候才执行tostring;第一次执行add的时候定义
 	inner.toString = function(){
 		return args.reduce( function (pre,acr ){
 			return pre+cur;
 		})
 	}
 	return inner
 }
 const result = add(1)(2)(3)(4)
 console.log(result);

//题目2
const nameList1 = [
	{mid:'1 ',profession:'adfsgaga '},
	{mid:'2 ',profession:'adfsgaga '},
	{mid:'3 ',profession:'adfsgaga '},
	{mid:4 ',profession:'adfsgaga '},
];

const nameList2 = [
	{adc:'4 ',profession:'adfsgaga '},
	{adc:'5 ',profession:'adfsgaga '},
	{adc:'6 ',profession:'adfsgaga '},
	{adc:'7 ',profession:'adfsgaga '},
];

const curring = name => element => element[name]  //柯里化函数
const name_mid =  curring('mid')
const name_adc =  curring('adc')
console.log(nameList1.map( name_mid))
console.log(nameList2.map( name_adc))
  1. vue keep-alive 常用属性
keep-alive是Vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在v页面渲染完毕后不会被渲染成一个DOM元素
//1. include、exclude属性
<keep-alive include="bookLists,bookLists">
      <router-view></router-view>
</keep-alive>
<keep-alive exclude="indexLists">
      <router-view></router-view>
</keep-alive>
include 表示name属性为bookLists,bookLists的组件需要被缓存;exclude表示只有name(组件最后export default{name:'bookLists'})为indexLists的组件不会被缓存;exclude属性不include优先级更高

首次进入组件时:beforeRouteEnter > beforeCreate > created> mounted > activated > … … > beforeRouteLeave > deactivated
再次进入组件时:beforeRouteEnter >activated > … … > beforeRouteLeave > deactivated

HTML

  1. HTML5新增了哪些内容或API,使用过哪些:click
  2. input和textarea的区别
input 是单行文本框,垂直居中显示
textarea是多行文本框
  1. 用一个div模拟textarea的实现
关键属性:contenteditable,可编辑的
	使用min-height和max-height另其超出范围出现滚动条
<div class = 'text_box' contenteditable = 'true'></div>
.text_box{
	width:100px;
	min-height:120px;
	max-height:300px;
	border:1px solid black;
	font-size:12px;
	word-wrap:break-word;//强制换行
	overflow-y:hidden;
	overflow-x:auto;
	padding:3px;
	margin:0 auto;
}
  1. 移动设备忽略将页面中的数字识别为电话号码的方法
<meta name = "format-detection"   content ="telephone = no">

css

  1. 左右布局:左边定宽、右边自适应,不少于3种方法
<div calss = 'box'>
	<div class = 'left'></div>
	<div class = 'right'></div>
</div>
//1 浮动布局
.left{width:200px;float:left;}
.right{width:100%;margin-left:200px;}

.box{clear:left}
.left{float:left;width:200px}
.right{float:left;width:calc(100vw - 200px)}

calc:四则运算,在css中动态计算长度值,运算符前后都需要保留一个空格;vm:viewpoart width,1vw=1% * viewport width,100vw = viewpoart width

//2 弹性布局
.box{dispwidlex;}
.left{width:200px;}
.right{width:100%flex:1;}

//3绝对定位
.left{width:200px;position:absolute;left:0;}
.right{width:100%;position:absolute;left:200px;}

//table布局
.box{diaplay:table;width:100%;}
.left{display:table-cell;width:200px;}
.right{display:table-cell}

//负margin
.box{ float:left;width:100%;}
.right{magin-left:200px;}
.left{margin-left:-100%;width:200px;float:left}

  1. CSS3用过哪些新特性click
  2. IFC
  3. 1像素边框问题,兼容性处理,手机端 click
原因:物理像素【设备像素】和逻辑像素【css像素】
pc端像素 :css像素 = 1:1
可以使用window.devicePixelRatio 获取比例,比例多少于设备有关
当devicePixelRatio == 2 ,border会被放大到2px
灵活方案:添加一个伪类,先将其大小放大2倍,再缩小到原来的1/2,再变换中心点
.demo{
	position:relative;
	widt:100px;
	height:100px;
	background-color:red;
}
.demo::after{
	content:'';
	box-sizing:border-box;
	position:absolute;
	left:.0;
	top:0;
	width:200%;
	height:200%;
	border:1px solid black;
	transform:scale(0.5);
	transform-origin:0 0;
	
}
  1. 如何让一个div水平居中?垂直居中?
水平居中:
	1 margin:0 auto;display:block;width:npx;
	2 父级:display:flex;垂直方向:align-items:center; 水平方向:justify-content:center;
垂直居中:
	1 父元素中设{display:flex;align-items:center;}
  1. img中alt和title的区别
图片中的alt属性是图片不能正常显示时出现的文本提示,alt有利于SEO
title属性是鼠标移动到元素上的文本提示。
  1. 用纯CSS创建一个三角形
border是以中心进行定位的,想要哪个位置三角形就将该位置的边设上颜色,其他边设为transparent
div{
	width:0;
	height:0;
	border-top:10px solid transparent;
	border-right:10px solid transparent;
	border-bottom:10px solid transparent;
	border-left:10px solid black;
}

div{
width: 0;
height: 0;
border-top: 100px solid black;
border-bottom: 100px solid red;
border-left: 100px solid #008c8c;
border-right: 100px solid yellow;
}
如图

在这里插入图片描述

JavaScript

  1. 图片懒加载 click
延迟加载,在需要的时候再加载
<img data-src = 'dfaafr.jpg'>
//方法一 : window.addEventListener('scroll')
缺点:滚动就会执行,图片被加载后但后续滚动时图片进入视口还是会重新加载
const images = documents.querySelectorAll('img')
window.addEventListener('scroll',(e)=>{
	images.forEach(image=>{
		const imageTop = image.getBoundingClientRect().top;
		if(imageTop<window.innerHeight){
			const data-src = image.getAttribute('data-src');
			image.setAttribute('src',data-src);
		}
	})
})
//方法二:intersectionObserver:目标元素和可视窗口会产生交叉区域
const images = documents.querySelectorAll('img')
const callback = entries =>{
	entries.forEach(entry =>{
		if(entry.isIntersecting){//进入交叉范围
			const img = entry.target;  //目标元素
			const data-src = image.getAttribute('data-src');
			image.setAttribute('src',data-src);
			observer.unobserve(image)              //!!!取消观察
		}
	})
}
const observe = new IntersectionObserver(callback);//每个被观察元素需要执行的回调函数
images.forEach(image=>{//为每张图片添加观察
	observer.observe(image);       //!!!添加观察
})
  1. 实现页面加载进度条
  2. 事件委托 click
    在这里插入图片描述
【事件】:用户操作触发了一段代码
【痛点】:
		绑定事件越多,浏览器占用内存越多,影响性能
		ajax实现的局部刷新,但操作相同,每次加载完都要重新绑定事件,耦合性过大
		部分浏览器移除元素时,绑定事件没有即使移除,导致内存泄漏
		
【事件机制设计原则】:绑定在父元素上的事件,用户在子元素也一样可以触发。
【事件委托】:子级的事件交给父级来实现,无需再给所有子级元素添加事件,只需要给父级元素进行绑定。每次捕获到事件就会抛出一个  event  对象,对象中的  target  属性是交互的具体子元素。

事件是在冒泡阶段被触发

做兼容
var event = e || window.event
var target = event.target || event.srcElement;
具体元素 : e.target
  1. 实现extend函数
  2. postMessage原理,h5用于解决跨域。 click
  3. 实现拖拽功能,比如把5个兄弟节点中的最后一个节点拖拽到节点1和节点之间
  4. 动画:setTimeout何时执行,requestAnimationFrame的优点 click
指定毫秒后调用。
requestAnimationFrame优点
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
  1. 手写parseInt的实现:要求简单一些,把字符串型的数字转化为真正的数字即可,但不能使用JS原生的字符串转数字的API,比如Number()
function  _parseInt(str,radix=10){//es6语法给形参默认值

   let str1 = str.trim()//去除空格
    //非字符串情况
    if(typeof str1 !== 'string' ){ //typeof返回值为字符串,需要加单引号或双引号 !!!,需要小写开头!!!
        return
    }
    //开头字符是否不是数字
    //方法1
    // let firstcode = str1.charCodeAt(0)  //charCodeAt大写字母是C、A,要使用字符串作为前缀!!!,括号内为index
    // if (firstcode>57 || firstcode<48){ //unicode中0为48
    //     return NaN
    // }

    //方法2
    // ^ 在正则中表示以后面内容为开头,此处为以数字为开头
    if(!str.match(/^\d/)){ 
        return NaN
    }
    
    //进制错误判断
    if(radix > 36 || radix < 2){
        return NaN
    } 
    //正则匹配两端进行界定的符号是斜杠!!,进行转义采用反斜杠
    //正则表达式不需要加引号!!
    let newstr = str1.match(/\d+/)[0]//此处[0]是match返回所有值中第一个元素!! 
    let realnum=0    //累加,初始值设为0

    //字符串不可以不经处理,直接使用下标的方式获取某位置的元素
    //方法1: 将字符串转化为数组,直接使用下标
    // let strarray = newstr.split('').join('')
    // let len = strarray.length
    // for(let i=0;i<len;i++){
    //     realnum += strarray[len-i-1] *Math.pow(radix,i)
    // }

    //方法2:可以使用substr返回字符
    let len = newstr.length
    for(let i=0;i<len;i++){
        realnum += newstr.substr(len-i-1,1) *Math.pow(radix,i)
    }
    return realnum
}

console.log(_parseInt('1235jhjk'))
  1. 编写分页器组件的时候,为了减少服务端查询次数,点击“下一页”怎样能确保还有数据可以加载(请求数据不会为空)?
  2. 1+any
    null、false转化为数字为0
    true转化为数组为1
    undefined NAN:not a number
    任何数值 + NAN = NAN
    NAN + ‘字符串’ = ‘NAN字符串’ 遇到字符串就开始字符串拼接
    字符串 + any = ‘字符串any’
    +[],表示加一个字符串,但[]为空字符串,所以没有加进去
    在这里插入图片描述
  3. == 和 ===区别是什么?js中的相等比较
基本数据类型,六个:number、string、null、undefined、symbol、boolean  ,存储在栈中,变量赋值为指针指向的过程,变量指向值
引用数据类型,五个:Date、Array、Object、function RegExp ,存储在堆中,变量指向堆中地址

对象存储在堆中,对象引用存储在栈中,如a = {n:1};  n:1存储在堆中的AAAFFF地址中,a 指向地址AAAFF1,   这个指向存储在栈中;b=a指的是b指向a的地址;b = {n:13}b指向新的堆,另外开辟了堆存储n:13,地址为AAAFFF2,b指向新地址。

堆:函数堆、对象堆、__proto_原型链面向对象的机制
【区别】 == 先转化类型再比较 ; ===先判断类型,如果不是同一类型直接为false,表示恒等于,两边要绝对相同
===深度比较
	1、如果类型不同,就[不相等]
	2、如果两个都是数值,并且是同一个值,那么[相等];(!例外)的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断)
	3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
	4、如果两个值都是true,或者都是false,那么[相等]。
	5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
	6、如果两个值都是null,或者都是undefined,那么[相等]。
==可以转换左右两边的数据类型,
	对象 == 对象:比较地址,因为对象存储在堆中,栈中指向的是堆中地址
	对象 == 字符串  :对象变为字符串,对象.toString 涉及Object.prototype.toString.call()
	NaN == NaN  :NaN和自己以及其他值都不想等
	null == undefined  :两个等于号想等,三个不相等,并且和其他值不相等
	剩下的情况,只要两边类型不同,最后都转换为【数字】,[]=false  => []=0,false=0 => true

	
	Object.is() 相对于 ==/===的好处
	

在这里插入图片描述

  1. JS模块化的实践
import {a1,a2,a3} from '../../adfa'
export {a1,a2,a3}  //导出整个模块
  1. 将函数的实际参数转化为数组的方法:
Array.prototype.slice.call(),将类数组转化为数组对象,令其可以使用数组的方法,如slice(用来截取字符串方法),可以使用对象的方法,如call(用于改变对象中函数内部的this引用)
var toArray = function(s){
	try{
		Array.prototype.slice.call(s)
	}catch(e){
		var arr = []
		for(var i =0,len=s.length;i<len;i++){
			arr[i] = s[i]
			//或使用push,速度较慢
			//arr.push(s[i])
		}
		return arr
	}
}
  1. require.js的实现原理(如果使用过webpack,进一步会问,两者打包的异同及优缺点)
  2. promise的实现原理,进一步会问async、await
留给promise
async + await
await 原理是generator(生成器函数,带有*),返回值为interator迭代器
function* gen(){
	//第一次进入到这,没有next不向下执行
	yield 1;  //每一个yield控制一个状态节点,每一个执行返回值为是否有下一个节点,下一个节点是谁;一个next执行到yield即结束,每次执行内容为本yield与上一个yield之间的内容。
	yield 2;
	yield 3;
}
const inter = gen(); //生成迭代器
conlose.log(inter.next())//
conlose.log(inter.next())
conlose.log(inter.next()) //当执行完成时inter.next()的返回值中done为true

function yieldPromise(generator){
	let interator= new generator() //是迭代器
	interatrorNext.call(interator) //interatrorNext拿到迭代器
}
function interatorNext(value){
	let interator = this,
		result = interator.next(value);
		
	if(result.done)return;//执行结束
	
	let val = result.value//继续执行
	/*Promise.resolve(val).then( val=>{
		interatorNext.call(interator,cal); 
	});*/
	//以上注释内容相当于,返回值为promise对象
	interatorNext.call(interator,cal);
}
async+await == *+yield
yieldPromise(function* (){ //生成器函数
 	let v1=yield Promise.resolve(100)
 	let v2=yield Promise.resolve(100)
})
  1. 实现gulp的功能
  2. 单页应用(SPA single page application),如何实现其路由功能 click
SPA避免了页面之间的切换,所有页面的代码都通过单个页面加载。
多页面应用:MPA,所有页面都是独立的,每访问一个页面都要重新加载html、css、js,公共文件按需加载
SPA,用户体验好,前后端分离,内容改变不需要重新加载真个页面,首次加载比较慢

hash,location.hash 和hashchange事件实现路由。用的较多,url中会出现 # ,
history api,使用html5的history api实现,主要是popstate事件,无 # ,但是需要后端配置
  1. javascript垃圾回收机制:找出不再使用的变量,然后释放掉其占用的内存(栈内存、堆内存)
    标记清除:click
    引用计次:click
javascript内存管理的主要概念就是可达性,可达性值可访问或可用。
根:固有可达值(本地函数的局部变量和参数、当前嵌套调用链上其他函数的变量和参数、全局变量)。可从根访问到的值就是可访问的。
垃圾:没有被引用的对象(var = nul)就是垃圾,例外:对象引用形成一个环,但跟访问不到它们,这个对象也是垃圾。
【常见内存泄漏方式】:
1 意外全局变量
function foo() {
    bar = "等价于创建global变量window.bar";
}

2 忘记清空的计时器
3 闭包中的循环引用
垃圾回收器:GC(Garbage Collecation)
【浏览器有自己的垃圾回收机制(栈内存+堆内存),原理分为两种】:
1 标记清除法 :谷歌。标记根,标记根的引用,再标记子孙代的引用;进程中不可被访问的对象被认为是不可访问的,将被清除。
2 引用计数法:IE。跟踪记录每个值被引用的次数(+1、-1),引用次数为0时,没有办法再访问这个值了,释放引用次数为0的值所占的内存。但循环引用时两个对象至少被引用1次,不可被回收。
【堆内存的释放】:变量 = null;【谷歌】变量没有被引用时,释放【IE】变量 = null  =>  占用减一,当前内存被引用 => 标记+1 ;弊端:很多情况下会计数不准,导致很多需要被清除的内存没有被清掉:内存泄漏。
【栈内存释放】:函数执行完,形成的执行上下文中没有东西被上下文以外的内容占用,此上下文就会从执行环境栈中移除(释放),如果被占用,则压缩到栈的底部(没有释放 == 闭包)
	优化技巧,尽可能减少对闭包的使用;局部变量使用let;组件销毁之前销毁定时器。

性能优化

  1. 项目中使用过哪 浏览器输入一个URL,Enter之后发生了什么 click

1、根据URL地址解析获得IP地址(在浏览器缓存中寻找,在系统缓存中寻找,发送到路由进行寻找,在DNS服务器进行寻找,在根域名服务器进行寻找)
2、建立TCP连接(三次握手)
3、发送http请求
4、服务端解析请求,返回响应头和内容
5、浏览器渲染页面(首先显示html文件,再请求其他静态资源,浏览器将其缓存并一 一进行渲染,浏览器还会请求不会缓存的异步处理的资源)
6、断开连接(四次挥手)

  1. (承上)页面的渲染过程,渲染树 click
  2. 静态资源或者接口等如何做缓存优化 click
  3. 页面DOM节点太多,会出现什么问题?如何优化?
dom节点增加,HTMLElement占用内存逐渐增加,监听事件等占用内存
卡顿极端情况会无响应
优化:
	【减少dom元素】:
			使用伪元素,尽量不要使用dom元素
			按需加载,减少不必要元素(懒加载?)
			结构合理,语义化标签
	【无法避免时】:
			缓存dom对象
			创建虚拟节点对象,但要防止文件结构被破坏:createDocumentFragment
			用innerHTML缓存高频appendChild		
  1. 如何尽快地定位到被改变的节点(承上)
  2. 同样一个域名,同时的并发请求最多能到多少 click
    太难了!!!!
  3. 页面的首屏优化:click
  4. 抓包 刷赞!!!!哈哈哈哈哈原来原理是抓包 click
  5. 有多个Tab标签页,都打开腾讯视频,出了问题你如何定位哪一tab的数据?
  6. HTTP请求报文、FTP、WebSocket,如何在抓包的时候过滤到想要的

计网

  1. TCP如何保证数据的完整性?它有一个确认的机制,如何完成这个机制
    首先【三次握手】建立链接:第一次握手是由客户端发起,客户端会向服务端发送一个报文,在报文里面:SYN标志位置为1,表示发起新的连接。当服务端收到这个报文之后就知道客户端要和我建立一个新的连接,于是服务端就向客户端发送一个确认消息包,在这个消息包里面:ack标志位置为1,表示确认客户端发起的第一次连接请求。以上两次握手之后,对于客户端而言:已经明确了我既能给服务端成功发消息,也能成功收到服务端的响应。但是对于服务端而言:两次握手是不够的,因为到目前为止,服务端只知道一件事,客户端发给我的消息我能收到,但是**我响应给客户端的消息,客户端能不能收到我是不知道的。**所以,还需要进行第三次握手,第三次握手就是当客户端收到服务端发送的确认响应报文之后,还要继续去给服务端进行回应,也是一个ack标志位置1的确认消息。通过以上三次连接,不管是客户端还是服务端,都知道我既能给对方发送消息,也能收到对方的响应。
    【三次握手和四次挥手】
    在这里插入图片描述

发送时【序列号和确认】 seq为我方的序列号,ack为期待对方的序列号
丢包会【超时重传】
网络拥塞有【拥塞控制】(慢启动阶段,传输包数量指数增加;到ssh进入拥塞避免阶段;拥塞避免阶段,线性增加;出现丢包,开始快恢复:将拥塞窗口大小设为ssh的一半,进入拥塞避免,并快重传丢的包)
在这里插入图片描述

为保证接收方不溢出有 【滑动窗口】
断开连接有【四次挥手】四次挥手也是客户端发起的,客户端会发送一个报文,报文FIN=1,当客户端收到这个报文之后,就知道了客户端想要和我断开连接,但是此时服务端有可能还有未发送完的报文消息需要继续发送,所以此时服务端只能告诉客户端我知道你要和我断开连接了,但是我这里可能还没做好准备,需要等我一下,等会我会告诉你,于是,发完这个消息确认报之后,稍过片刻之后服务端继续发送一个断开连接的报文,FIN=1,表明服务端已经做好断开连接的准备,那么,当这个消息发给客户端的时候,客户端同样需要继续发送一个消息确认的报文,那么通过这四次的相互沟通和连接,我就知道了,不管是客户端还是服务端,都已经做好了断开的准备。

  1. 滑动窗口是用于解决什么问题的?
滑动窗口是传输层进行流量控制的一种措施。接收方通过通知发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的,并且滑动窗口分为接收窗口和发送窗口。TCP的滑动窗口的可靠性是建立在“确认重传”基础上的。发送窗口只有收到对方对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界(以便超时重传)。接受窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认,而是发送三次上一个序列号的ACK。
  1. 服务端收到了,回ACK包的时候客户端没收到,客户端又发了一个包,它不会重复吗?服务端如何确认是同一个包

    序列号相同?是这样吗

  2. CRC校验是怎样做的
    CRC:循环冗余校验码,数据传输检错功能,对数据进行多项式模2运算,得到结果附在帧的后面,接收设备也进行相同运算,以来保证数据传输的正确性和完整性。

例:现假设选择的CRC生成多项式为G(X) = X4 + X3 + 1,要求出二进制序列10110011的CRC校验码?

(1)首先把生成多项式转换成二进制数,它的二进制比特串为11001。

(2)因为生成多项式的位数为5,得CRC校验码的位数为4(校验码的位数比生成多项式的位数少1)。因为原数据帧10110011,在它后面再加4个0,得到101100110000,然后把这个数以“模2除法”方式除以生成多项式,得到的余数(即CRC码)为0100,如下所示。
在这里插入图片描述
(3) 把上步计算得到的CRC校验0100替换原始帧101100110000后面的四个“0”,得到新帧101100110100。再把这个新帧发送到接收端。

(4)当以上新帧到达接收端后,接收端会把这个新帧再用上面选定的除数11001以“模2除法”方式去除,验证余数是否为0,如果为0,则证明该帧数据在传输过程中没有出现差错,否则出现了差错

PS: “模2除法”与“算术除法”类似,但它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可。模2加法运算为:1+1=0,0+1=1,0+0=0,无进位,也无借位;模2减法运算为:1-1=0,0-1=1,1-0=1,0-0=0,也无进位,无借位。相当于二进制中的逻辑异或运算。也就是比较后,两者对应位相同则结果为“0”,不同则结果为“1”。如100101除以1110,结果得到商为11,余数为1。

  1. TCP和UDP的区别是什么?谁的包会大一些 click
    TCP建立可靠传输,需要通过三次握手来建立连接,数据传递时有确认、滑动窗口、超时重传、拥塞控制,数据传输完成会断开连接。缺点:慢、效率低、占用系统资源高、易被攻击。
    DUP,快,安全,无需建立连接,是一个无状态的传输协议,不可靠、不稳定,容易丢包。
TCPUDP
是否连接有链接无连接
传输可靠性可靠不可靠
应用场合少量传输传输大量数据
报文流模式,有流量控制(滑动窗口)数据报模式,基于报文,每次读取一个报文

UDP 最大:1500 - IP头(20) - UDP头(8) = 1472(Bytes),最小:60
TCP 最大:1500 - IP头(20) - TCP头(20) = 1460 (Bytes).最小:54
用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535- IP头(20) - UDP头(8)=65507字节。

用TCP协议发送时,由于TCP是数据流协议,因此不存在包大小的限制(暂不考虑缓冲区的大小)。数据比较长,会被分段发送,如果比较短,可能会等待和下一次数据一起发送。

  1. 设计一套聊天系统,保证聊天内容有序不丢包,然后离线的时候还要能正常收发,我是采用TCP还是UDP。

UDP为主,TCP为辅,每一个用户都是和服务器交互,再由服务器转发给正在通信的用户。若从上线到下线全部采用TCP长连接,对服务器负担太大,若使用TCP短链接,频繁链接会给网络造成负担。采用UDP可以避免,减少了服务器负担。

  1. 粘包和拆包
    在这里插入图片描述
    【发生粘包原因】:
    应用程序写入的数据小于套接字缓冲区的大小,但网卡将应用多次写入的数据一次性发送到网络
    接收方不及时读取套接字缓冲区中的数据

【发生拆包原因】:
应用程序写入的数据大于套接字缓冲区的大小,
进行TCP分段,长度为MSS(最大报文长度),当TCP报文长度 - TCP 头部长度 > MSS的时候发生拆包

  1. get请求和post请求有什么区别??
「GET」
一般用于获取数据基于URL地址传参,所以有个长度限制(一般在8KB左右),如果超过就会被截掉因为GET请求基于问号传参容易被劫持,所以相对不安全。会产生不可控制的缓存,POST不会

「POST」
一般用于新增数据基于请求传参,理论上没有任何限制(真实项目中会自己做大小限制,防止上传过在信息导致请求迟迟完不成)PSOT请求基于请求主体传参,相对来说不好被劫持,比较安全
  1. 四层:应用层(HTTP数据:)、传输层(TCP:街道)、网络层(IP:市)、链路层(以太网:省)
    在这里插入图片描述

  2. web缓存 / 浏览器缓存 / http缓存
    文章:[click]((https://blog.csdn.net/u012375924/article/details/82806617)
    视频:click

强制缓存协商缓存
「强制缓存」
当浏览器向服务器发送请求的时候,服务器会将缓存规则放入HTTP响应的报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires(绝对过期时间)和Cache-Control(相对过期时间),其中Cache-Conctrol的优先级比Expires高。在时间之内会直接读取缓存中的数据。

「协商缓存」
协商缓存就是【缓存过期(cache-control的值,即时间)】后,浏览器携带 缓存标识( if-Modified-Since 或 if–None-Match) 向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。缓存过期后向服务器发送请求,缓存是否有Last-Modified 或 ETag,没有要向服务器发送HTTP请求;若存在标识,请求头要携带 标识 发送HTTP请求,未过期返回304,从本地读取资源,若过期则返回200状态码 + 最新的资源 + 资源标识。
浏览器第一次请求后,服务器返回资源和资源标识,资源缓存到本地缓存中;
以后再请求会发送请求和资源标识,服务器会对资源标识和资源进行比较,
若一致则返回304状态码,浏览器直接从缓存中读取资源;
若资源有更新过,则返回200状态码 + 最新的资源 + 资源标识。
资源标识:Last-Modified(只能精确到秒):资源上一次修改时间(响应头),再次请求的时候 请求头 中就可以加上最新修改事件,名字为 if-Modified-Since。
ETag(优先使用):资源对应的唯一字符串(用以应对最后修改时间变了,但内容并没有变的情况)下次请求的时候请求头中加上标识:if–None-Match

强制缓存优先于协商缓存进行,若强制缓存生效则直接使用缓存,若不生效则进行协商缓存,协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存

请求头和响应头都有cache-control
在这里插入图片描述

  1. WEB安全及防护原理
    CSRF:click
CSRF:Cross Site Request Forgert ,跨站点请求伪造
攻击者盗用用户身份,以用户的名义发送恶意请求,从get参数中获取
解决方法:
	1 使用post请求
	2 加入验证码
	3 验证refer,网页是否同源
	!!4 Anti CSRF Token ,在form表单或头信息中传递token,服务器存储在服务端,客户端放在session,或redis的nosql缓存中,post请求时带给服务端,服务端通过拦截器验证有效性,拒绝校验失败的请求
		<meta name = 'csrf-token' content = ‘服务器生成’ >
	加入自定义Header

XSS(跨站脚本攻击 Cross SiteScript):click

Cross Site Scripting 跨站脚本
访问目标站点,html渲染过程中,一些没有预期到的脚本指令被执行,该脚本获得一些用户的信息,如将cookie发送到攻击者自己的网站
产生原因:对url或用户输入没有进行充分的过滤,将不合法的参数或内容到了服务器,用户前端页面进行渲染非法脚本。
危害:
	挂马
	盗取cookie
	删除文章
	蠕虫
类型:
	反射型:服务器返回脚本,客户端执行,内容出现在url中
	存储型:后台存储了非法脚本,并且前端直接展示
	DOM-Based型:基于DOM或本地的XSS攻击
方法:
	对输入(和url参数、post请求、ajax)进行过滤:对script标签进行过滤、转义。
	对输出进行编码:转义 ,< 转义为 &lt  ;>转义为 &gt  、、、
	响应头添加set-cookie参数,参数值添加http-only,实现js脚本无法读取cookie
	配置CSP(content security prolity,指定能够加载和执行的资源)

SQL注入:通过sql命令插入到web表单、输入域名、页面请求的查询字符串中,以达到七篇服务器执行恶意sql命令。
方法:对用户输入进行校验,通过正则表达式对单引号双-进行转化
不使用动态拼接sql,可以使用参数化的sql、或存储过程进行数据查询存取
不要使用管理员权限查询数据,为每个应用使用单独权限的数据库连接
不要把机密信息明文存放,加密或hash掉密码等敏感信息

vue

  1. 常用vue api原理(包括不限于nextTick,watch,computed)
  2. 原生Ajax和axios的区别,Ajax怎么发送http请求的?
	原生Ajax是根据 XMLHttpRequest发HTTP请求,而axios是根据Ajax进行封装的插件,其内部利用Promise实现,很好的解决的异步请求回调地狱的问题。
  1. computed和watch区别
计算属性computed和监听器watch都可以观察属性的变化从而做出响应,不同的是:

计算属性computed更多是作为缓存功能的观察者,它可以将一个或者多个data的属性进行复杂的计算生成一个新的值,提供给渲染函数使用,当依赖的属性变化时,computed不会立即重新计算生成新的值,而是先标记为脏数据,当下次computed被获取时候,才会进行重新计算并返回。

而监听器watch并不具备缓存性,监听器watch提供一个监听函数,当监听的属性发生变化时,会立即执行该函数。
  1. VUE和REACT有什么区别?

  2. vue路由的两种模式,
    解决问题:前后端分离 + 单页面应用,渲染不同页面通过更改路由,加载不同组件,动态渲染html内容,不发送请求,不请求服务器。
    1、hash模式(vue-router默认hash模式):通过URL的hash模拟完整URL,也url改变,会触发hashchange事件,根据hash值更新页面内容;访问路由时,hashHistory对象会发生HashHistory.push():添加新路由到浏览器访问历史栈顶、HashHistory.replace():替换当前栈顶路由

      window.onhashchange = function(event){
        console.log(event);
      }
    

    2、history模式:HTML5的pushstate(往历史记录堆栈顶部添加一条记录)和replaceState(读取历史记录栈,对浏览器记录进行修改);history包括(back、forward、go三个方法)window.onpopstate:响应pushState、replaceState
    编码

  3. 实现一个简单的Promise发布订阅者模式(观察者模式) promise所有函数
    观察者模式:当对象存在一对多的关系时使用观察者模式(一对一模式是单例模式),当一个对象修改时,会自动通知它依赖的对象

  4. 手动写一个node服务器

const express = require('require')
const app = express()
app.listen(3001,(err)=>{
	if(!err){
		console.log('访问地址:localhost:3001')
	}else{
		console.log(err)
	}
})

算法 200easy+50middle

  1. 实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
function clone(obj){
    console.log(Object.prototype.toString.call(obj))
    
    if( Object.prototype.toString.call(obj) == '[object Object]'){
        let copy = {}
        for(let item in obj){
            copy[item] = clone(obj[item])
        }
        return copy
    }else if(Object.prototype.toString.call(obj) == '[object Array]'){//用于监测所有类型的方法
        let copy = [];
        let i = obj.length
        while(i--){  //写在这不管时--i 还是i-- 都是一样的
           copy[i]=clone(obj[i])
        }
        return copy
    }else{
        return  obj
    }
}
let obj = [8,2,6,[8,5,1]]
let obj1 = {'a':1,'b':2}
let obj2 = true
let obj3= 123
let obj4='fsfaef'
let obj5=null
let obj6=undefined
let time=6

console.log(clone(obj))
console.log(clone(obj1))
console.log(clone(obj2))
console.log(clone(obj3))
console.log(clone(obj4))
console.log(clone(obj5))
console.log(clone(obj6))

在这里插入图片描述

  1. 数组去重
function unique(array){
   let len = array.length
    let arraynew=[]
    for(let i=0;i<len;i++){
        if(arraynew.indexOf(array[i])==-1){  //!!!indexof,
            arraynew.push(array[i])
        }
    }
    return arraynew
}
let array=[1,5,7,6,2,4,1,2]
console.log(unique(array))
  1. promise.all 异常处理
  2. 版本号比较排序
var arr = ['0.1.0', '2.2.3', '0.3003.1', '4.3', '4.3.6', '4.3.3.5']
arr.sort((a,b)=>{
    let items1=a.split('.')   //split之后为数组
    let items2=b.split('.')
    let len = items1.length
    for(let i =0 ;i<len;i++){   //两数组元素进行比较一定要用下标,不要犹豫
        if(items1[i]==items2[i]){    //  想等就要比较下一个数
            continue
        }
        return items1[i] - items2[i]     //sort数组返回值为    差    ;不是   true  / flase
    }
})
console.log(arr)
  1. node 中 promisify 实现
  2. fetch 兼容超时重传
  3. String indexOf 实现
String.prototype.subString=function(start,len){  //有等号和function
 //this 为str
    let substr=[]
    for(let i =start;i<start+len;i++){
        substr.push(str.charAt(i))
    }
    return substr.join('')//将数组使用 ''连接起来,与spllit相反操作
}

String.prototype.indexOf=function(smallStr){
    // this即为str
    let str = this
    let time = str.length-smallStr.length
    for(let i =0;i<=time;i++){
        if(str[i]==smallStr.charAt(0) && str.subString(i,smallStr.length)==smallStr){
            return i
        } 
    }
    return -1
}
let str = 'asdfg'
let smallStr = 'fg'
console.log(str.indexOf(smallStr))   //字符串类型原型设了函数后,调用方法为字符串.function(arguments),谁调用this就是谁,不管是function还是str
  1. 扁平化
function flat(array){
    debugger
    let newArr=[] //每次迭代都是使用自己内部newArr,每次都是空数组,多次迭代之间不影响
    let len = array.length
    for(let i =0;i<len;i++){
        if(Object.prototype.toString.call(array[i]) == '[object Array]'){
            newArr=newArr.concat(flat(array[i])) //返回一个数组,元素组和新数组进行拼接
        }else{
            newArr.push(array[i]) //不能通过下标进行修改!!使用push即可!!
        }
    } 
    return newArr    //切记返回!!!!,不返回拿不到啊!!!
}
let array = [1,2,3,8,[8,5,6],5,[9,1,4,6]]
console.log(flat(array))

不区分

  1. webpack打包原理、如何写webpack插件(loader,plugin的区别,怎么实现loader,plugin,自己有没有写过,webpack整个流程是什么样的,这边建议自己去手写个简单的webpack玩玩,就全知道了,本质上就是广度递归而已)
  2. 状态码
    200 OK 成功(最理想的状态)
    301 Moved Permanently 永久转移(永久重定向)
    302 Move temporarily 临时转移
    304 Not Modified 设置缓存
    400 Bad Request 请求参数错误
    401 Unauthorized 无权限访问
    404 Not Found 找不到资源(最不理想的状态)
    405 Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源,但是该响应必须返回一个Allow头信息来表示出当前资源能够接受请求方法的列表。
    500 Internal Server Error 未知的服务器错误
    503 Service Unavailable 服务器超负荷
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值