大家好,又见面了,我是你们的朋友全栈君。
'use strict'
var name = 'Jay'
var person ={
name : 'Wang',
pro:{
name:'Michael',
getName:function(){
return this.name;
}
}
}
console.log(person.pro.getName());
var pepole = person.pro.getName;
console.log(pepole());
答案
Michael
throw error
因为在'use strict'严格模式下,this无法指向全局,所以报错。当把'use strict'拿掉之后就是this.name的this指向person全局的name
结果为 michael Wang
setTimeout(function(){
console.log(1)
},0);
new Promise(function executor(resolve){
console.log(2);
for(var i= 1; i<10000; i+=1 ){
i>=9999&&resolve();
}
console.log(3)
}).then(function(){
console.log(4)
})
console.log(5)
//答案
2
3
5
4
1
解析:首先将定时器里的回调函数添加到宏任务队列中,实例化Promise对象,同步执行执行器的executor()函数输出2,改变promise的状态为resolve,输出3,将then回调函数的添加到微任务队列中,输出5.同步代码执行完毕,执行异步任务;查看微任务队列,执行then回调函数输出4,微任务执行完毕,查看宏任务队列,执行settimeout的回调函数输出1
function fn(str,arr){
for(let item of arr){
let len = item.length
let ret = new RegExp(`${
item}`,'g')
str = str.replace(ret,'*'.repeat(len))
}
return str
}
console.log(fn('想要轻生,have sex,sexy,babe',['轻生','sex']))
//结果
VM1759:11 想要**,have ***,***y,babe
A.git是由github创造的代码管理工具
B.git和svn实现的原理是一样的
C.从git原理设计上来讲,执行git pull和先执行git fetch再执行git merge效果是一样的。
D.git将代码提交到远程仓库的命令是git commit
E.git rm只会将文件从git提交记录中删除,不会删除磁盘上的物理文件
F.git push -f将会重新提交当前的commit节点,不会重写历史commit
答案C
A.Cookie,LocalStorage和IndexedDB都会受到同源策略的限制
B.postMessage,JSONP,WebSocket都是常用的解决跨域的方案
C.跨域资源共享规范中规定了除了GET之外的HTTP请求,或者搭配某些MINE类型的POST请求,浏览器都需要先发一个OPTIONS请求
D.http://www.bilibili.com和https://www.bilibili.com是相同的域名,属于同源
答案:d
https和http是不同协议
A.在并行程度中,当两个并行的线程,在没有任何约束的情况下,访问一个共享变量或者共享对象的一个域,而且至少要有一个操作是写操作,就可能发生数据竞争错误。
B.原语Compare-and-swap(CAS)是实现无锁数据结构的通用原语。
C.获得内部锁的唯一途径是:进入这个内部锁保护的同步块或方法。
D.volatile变量具有synchronized的可见性特性,但是不具备原子特性。
E.减小竞争发生可能性的有效方式是尽可能缩短把持锁的时间
答案ABCDE
下面数据结构能够支持随机的插入和删除操作、并具有较好的性能的是____。
正确答案: B 你的答案: F (错误)
A.数组和链表
B.链表和哈希表
C.哈希表和队列
D.队列和堆栈
E.堆栈和双向队列
F.双向队列和数组
根据关系型数据库规范范理论,关系数据库中的关系要满足第一范式,在部门关系中,因哪个属性而石塔不满足第一范式?()
正确答案: B
A.部门名
B.部门成员
C.部门总经理
D.部门号
解析:第一范式要保证原子性,不能进行再次分层。
现有4个同时到达的作业J1,J2,J3和J4,它们的执行时间分别是1小时,3小时,5小时,7小时,系统按单道方式运行且采用短作业优先算法,则平均周转时间是()小时
正确答案: D
A.4
B.5
C.6
D.7.5
解析:谁短谁先执行,所以执行顺序为 J1 J2 J3 J4,J1执行完时间为1,轮到J2执行时,前面已经过了一小时,所以J2执行完时间为1+3 =4,同理,平均周转时间为 (1 + (1+3) + (1+3+5 )+ ( 1+3+5+7))/4=7.5
var foo = "Hello";
(function(){
var bar = " World";
alert(foo + bar);
})();
alert(foo + bar);
其中alert两次输出结果为?
hello world 报错
考察就是作用域问题
寝室有6个同学打dota,分为对立的两方,一方是天灾军团,一方是近卫军团。现请你设置赛程以及每场的对阵(每方最少1人、最多5人),请问至少得进行多少场比赛,才能使得赛程结束后每位同学都和其他同学做过对手()
假设 A B C D E F 六位同学
第一场: ABC * DEF
第二场: ABF * DEC
第三场: BDF * EAC
计算机内的传输是并行传输,通信线路上的传输是串行传输
setTimeout(() => console.log('a'));
Promise.resolve().then(
() => console.log('b’);
).then(
() => Promise.resolve('c').then(
(data) => {
setTimeout(() => console.log('d'));
console.log('f');
return data;
}
)
).then(data => console.log(data));
//
// 定时器任务属于宏任务,并且需要先在任务队列等待,等到同步任务执行完,执行栈清空,才会在任务队列中按顺序选任务进去
setTimeout(() => console.log('a'));//4. 打印a
//Promise 属于异步微任务,在本轮同步任务结束之前执行
Promise.resolve().then(
// 1. 打印 b
() => console.log('b') // 单引号要改为',然后去掉;号
).then(
// 箭头函数的resolve传递的参数作为下一个then的参数
() => Promise.resolve('c').then(
// 执行箭头函数
(data) => {
// 把定时器任务也放入任务队列中等待,在第一个定时器之后
setTimeout(() => console.log('d')); //5. 打印d
// 2.打印 f
console.log('f');
// 此时返回的 数据作为下一个then的参数
return data;
}
)
).then(data => console.log(data)); // 3.打印 c
``` * `打印bfcad`
请写出下面ES6代码编译后所生成的ES5代码;
class Person {
constructor (name) {
this.name = name;
}
greet () {
console.log(`Hi, my name is ${
this.name}`);
}
greetDelay (time) {
setTimeout(() => {
console.log(`Hi, my name is ${
this.name}`);
}, time);
}
}
var Person = (function () {
function Person (name) {
this._name = name;
}
Person.prototype.greet = function () {
console.log(“Hi, my name is “ + this._name);
}
Person.prototype.greetDelay = function (time) {
var _this = this;
setTimeout(function () {
console.log(“Hi, my name is “ + _this.name);
}, time);
}
})();
形如1, 1, 2, 3, 5, 8, 13, 21, 34, 55的数列,后一位是前面两位相加(斐波那契数列),写出函数要求找到第 N 位是多少,如:fib(3) => 3 , fib(5) => 8, 要求时间复杂度为O(n)。
function fib(n){
let top=1,bottom=0,res=0
for(let i=0;i<n;i++){
res=top+bottom
bottom=top
top=res
}
return res
}
给定一个包含非负整数的 M x N 迷宫,请找出一条从左上角到右下角的路径,使得路径上的数字总和最小。每次只能向下或者向右移动一步。
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
ouput: process.stdout
})
let inArr = []
rl.on('line', line=>{
if(!line) return
inArr.push(line.trim())
let mn = inArr[0].split(' ').map(e=>+e)
let m = mn[0]
let n = mn[1]
if(inArr.length === m+1){
let arr = []
for (let i = 0; i < m; i++) {
arr[i] = inArr[i+1].split(' ').map(e => +e)
}
console.log(minPathSum(arr))
}
})
var minPathSum = function (grid) {
const m = grid.length,
n = grid[0].length
for (let i = m - 1; i >= 0; i--) {
for (let j = n - 1; j >= 0; j--) {
if (i + 1 < m && j + 1 < n) {
grid[i][j] += Math.min(grid[i + 1][j], grid[i][j + 1])
} else if (i + 1 < m) {
grid[i][j] += grid[i + 1][j]
} else if (j + 1 < n) {
grid[i][j] += grid[i][j + 1]
}
}
}
return grid[0][0]
};
小团在一次星际旅行中,耗尽了飞船的能量,迷失在了空间魔方中,空间魔方中有N*N**N个能量粒子。美团云AI迅速帮小团分析出了空间魔方的能量分布图。
已知小团的飞船被困在能量值最高的点,能量值最高点有且只有一个。飞船每到达一个能量粒子就会吸收对应粒子的能量,该粒子会坍缩成小黑洞,飞船不可到达。小团驾驶的飞船只能从高能粒子驶向低能粒子,且每次只能从6个方向中选择一个前进。(±x,±y,±z)。
请帮助帮小团吸收最高的能量值。
new Promise((resolve) => {
console.log('1')
resolve()
console.log('2')
}).then(() => {
console.log('3')
})
setTimeout(() => {
console.log('4')
})
console.log('5')
js在处理异步操作时利用的是事件循环机制。事件循环机制处理顺序,同步操作<-异步操作(微任务<-宏任务)
由于javascript是单线程任务所以主线程只能同时处理一个任务,所以把异步的事件放在同步的事件处理完成之后再来依次处理。
异步事件又包括微任务和宏任务:
宏任务和微任务关系:微任务执行完后再执行宏任务
微任务操作:1:Promise,2:MutationObserver
宏任务操作:1:setTimeout,2:setInterval,3:I/O操作
所以上面代码执行顺序为:
同步:console.log(1)->console.log(2)->console.log(5);
异步:(微任务)console.log(3)->(宏任务)console.log(4);
所以答案为:1 2 5 3 4
请列举几个HTML5语义化标签,并说说语义化有什么优点?
<title>:页面主体内容。
<hn>:h1~h6,分级标题,<h1> 与 <title> 协调有利于搜索引擎优化。
<ul>:无序列表。
<li>:有序列表。
<header>:页眉通常包括网站标志、主导航、全站链接以及搜索框。
<nav>:标记导航,仅对文档中重要的链接群使用。
<main>:页面主要内容,一个页面只能使用一次。如果是web应用,则包围其主要功能。
<article>:定义外部的内容,其中的内容独立于文档的其余部分。
<section>:定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。
<aside>:定义其所处内容之外的内容。如侧栏、文章的一组链接、广告、友情链接、相关产品列表等。
<footer>:页脚,只有当父级是body时,才是整个页面的页脚。
<small>:呈现小号字体效果,指定细则,输入免责声明、注解、署名、版权。
<strong>:和 em 标签一样,用于强调文本,但它强调的程度更强一些。
<em>:将其中的文本表示为强调的内容,表现为斜体。
<mark>:使用黄色突出显示部分文本。
<figure>:规定独立的流内容(图像、图表、照片、代码等等)(默认有40px左右margin)。
<figcaption>:定义 figure 元素的标题,应该被置于 figure 元素的第一个或最后一个子元素的位置。
<cite>:表示所包含的文本对某个参考文献的引用,比如书籍或者杂志的标题。
<blockquoto>:定义块引用,块引用拥有它们自己的空间。
<q>:短的引述(跨浏览器问题,尽量避免使用)。
<time>:datetime属性遵循特定格式,如果忽略此属性,文本内容必须是合法的日期或者时间格式。
<abbr>:简称或缩写。
<dfn>:定义术语元素,与定义必须紧挨着,可以在描述列表dl元素中使用。
<address>:作者、相关人士或组织的联系信息(电子邮件地址、指向联系信息页的链接)。
<del>:移除的内容。
<ins>:添加的内容。
<code>:标记代码。
<meter>:定义已知范围或分数值内的标量测量。(Internet Explorer 不支持 meter 标签)
<progress>:定义运行中的进度(进程)。
优点:
代码结构清晰,方便阅读,有利于团队合作开发。
方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。
有利于搜索引擎优化(SEO)。
请列举几种除了px外的CSS度量单位并解释其含义。
1. rem 相对于根字体大小的单位,比如可以设置 1rem=50px
2. em 相对于font-size,比如font-size:16px(浏览器默认),则2em=32px
3. vm 即viewpoint width,视窗宽度,比如1vm的宽度为相对于视窗的宽度的百分之一
4. vh 即viewpoint height ,同上
简述cookie/session记住登录状态机制原理。
用户登录验证成功后,如果是使用 Cookie 记住登录状态,则服务器会将用户名等信息放在响应头的 Set-Cookie 属性中返回给服务器,之后的 HTTP 请求都会携带这个 Cookie ,实现记住登录。如果是 session 的话,则服务器会将用户名等信息存放在本地,再随机生成一个登录标识通过 Cookie 返回给浏览器,之后浏览器每次发送请求也会携带这个 Cookie,服务器收到后便通过这个标识得到已登录的用户信息。
网页中接收事件的顺序(事件流)有哪些?它们之间的区别是什么?
有捕获和冒泡两种,冒泡是事件由子元素传递到父元素的过程,捕获是时间由父元素传递到子元素的过程
css属性position都有哪些值?
absolute绝对定位
relative相对定位
fixed固定定位
sticky粘性定位
static默认值,没有定位
inherit继承父系
initial设置该属性为默认值
简述你对HTTP控制访问(CORS)的理解。
首先要搞明白什么是同源,什么是跨域。
打一个简单的比方,你自己从你家里拿东西,不会有人说,这是同源;但是你要从隔壁的邻居的冰箱去拿可乐,你觉得可能吗,这就是跨域。
从比方中回来,事实其实没有那么简单。理解了概念后,得知道如何去判断同源还是跨域。web服务器有三要素:协议(http、https)、端口号(不过多说)、web服务器域名(比如https://github.com/mamba666
中https://github.com就是域名)。三要素必须全部一致才算同源
个人认为写完上面的东东后已经理解了同源跨域已经如何区分。接下来就来看看真正的干货,不讲同源,只讲跨域(以下参考MDN)
浏览器端
如果发现有一个请求是跨域,那么浏览器会自动先拦截一下,给它的http header加上Origin字段。比如 http://localhost:8080变为Origin:http://localhost:8080。这样一来,服务器端就可以区分这个请求是不是跨域了。
服务器端
当服务器端收到浏览器端发送过来的请求后,会有一个响应header。它会告诉请求的浏览器哪儿些域名可以请求我,哪儿些方法可以执行。
响应回到浏览器端
此时浏览器会根据这个响应自动判断,然后在做决定。
服务器端返回给浏览器端的东西
Access-Control-Allow-Origin 允许跨域的Origin列表
Access-Control-Allow-Methods 允许跨域的方法列表(GET、POST等)
Access-Control-Allow-Headers 允许跨域的Header列表
Access-Control-Expose-Headers 允许暴露给JavaScript代码的Header列表
Access-Control-Max-Age 最大的浏览器缓存时间,单位为s
跨域请求形式
有两种,简单和非简单请求。这里说说我常遇到的 application/json 。这就是一种非简单请求,在以上所写的浏览器端之前,会先进行一次预请求,根据这个结果再去判断是否正式请求。
以下关于块级元素和行内元素的说明正确的是?
A.块级元素在默认情况下,其宽度自动填满其父元素的宽度
B.块级元素的width、height属性可以生效,但padding、margin无效
C.strong属于行内元素, 它的width、height属性设置无效
D.textarea默认属于块级元素,而input属于行内元素
1.块级元素会独占一行,默认情况下,其宽度自动填满其父元素宽度。
行内元素不会独占一行,相邻的行内元素会排列在同一行里,直到一行排不下,才会换行,其宽度随元素的内容而变化。
2.块级元素的padding和margin值的设置都是有效的。行内元素和块级元素都是盒子模型。
行内元素的padding-top、padding-bottom、margin-top、margin-bottom属性设置是无效的(top bottom)
行内元素的padding-left、padding-right、margin-left、margin-right属性设置是有效的(left right)
行内元素的 line-height 属性设置是有效的。
行内元素的 width、height 属性设置是无效的。
行内元素的padding-top、padding-bottom从显示的效果上是增加的,但其实设置的是无效的,并不会对他周围的元素产生任何影响
3.strong是行内元素,它的width、height属性设置无效(没错啊???)
4. textarea是行内元素 - 多行文本输入框,input也是行内元素
行内inline 块级block 行内块级line-block(拥有内在尺寸,可设置高宽,不会自动换行 )
以下关于cookie和localStorage描述正确的是
A.cookie 和 localStorage 都可以由浏览器自动携带在http请求的header中传递给服务端
B.localStorage无法被用户清除,所以比Cookie更安全,可以放置重要数据
C.localStorage 和 cookie 一样也有跨域限制
D.localStorage 可以和cookie 一样通过特殊的http 头部由服务端进行设置
function fun () {
return () => {
return () => {
return () => {
console.log(this.name)
}
}
}
}
var f = fun.call({
name: 'foo'})
var t1 = f.call({
name: 'bar'})()()
var t2 = f().call({
name: 'baz'})()
var t3 = f()().call({
name: 'qux'})
箭头函数没有自己的this也并不能使用call,apply以及bind去绑定this,会选择去继承父级作用域的this,所以后面几次的call实际上是失败的,所以箭头函数层层向上寻找name,只会在最外层的fun函数作用域中找到this指向{name: 'foo'}对象的name属性。假设此处将fun函数改成箭头函数的声明方式,那么返回的值将会是undefined.
小易有个32G字节的文件,需要从电脑1传送到电脑2,假设两者之间是1024Mbit/s的网络,那么需要多久能传输完 ?
一字节等于8位
32 * 8 * 1024 M bit /1024Mbit/s = 256s
下面代码执行结果是
const a = {
valueOf() {
return 'valueOf'
},
toString() {
return 'toString'
},
get() {
return 'get'
}
}
alert(a)
这题考查valueOf()与toString()的区别。
在不重写这两个方法时:
toString()方法:返回对象的字符串表示
valueOf()方法:返回指定对象的原始值。
默认情况,会调用toString()方法。例如:
var cc = {
};
alert(cc);// [object Object]
var fun = function() {
} ;
alert(fun);// function() {}
var arr = [1];
alert(arr); // 1
从上面的代码来看,默认情况会调用对象的toString()方法,返回对象的字符串表示。
下面看看重写对象的toString()与valueOf()方法,并且同时存在时会发生什么:
var bbb = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
},
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bbb);// 10 toString
alert(+bbb); // 10 valueOf
alert(''+bbb); // 10 valueOf
alert(String(bbb)); // 10 toString
alert(Number(bbb)); // 10 valueOf
alert(bbb == '10'); // true valueOf
二者并存的情况下,在数值运算中,优先调用了valueOf,字符串运算中,优先调用了toString。而’ '+bbb是字符串操作,为啥也是调用valueOf,那是因为,存在操作符,valueOf的优先级高于toString。
回到本题: alert(obj)不存在数值运算,和其他操作符,所以默认调用toString方法。
结果为:toString。
js将数字转为中文
function transform(tranvalue){
try{
//转换整数部分
var k1=0;//计小单位
var k2=0;//计大单位
var sum = 0;
var str="";
var len = source[0].length;//整数的长度
for(i=1;i<=len;i++){
var n = source[0].charAt(len-i);//取得某个位数上的数字
var bn = 0;
if(len-i-1>=0){
bn = source[0].charAt(len-i-1);//取得某个位数前一位上的数字
}
sum = sum+Number(n);
if(sum!=0){
str = dw[Number(n)].concat(str);//取得该数字对应的大写数字,并插入到str字符串的前面
if(n=='0')sum = 0;
}
if(len-i-1>=0){
//在数字范围内
if(k1!=3){
//加小单位
if(bn!=0){
str = dw1[k1].concat(str);
}
k1++;
}else{
//不加小单位,加大单位
k1=0;
var temp = str.charAt(0);
if(temp=="万" || temp=="亿")//若大单位前没有数字则舍去大单位
str = str.substr( 1, str.length-1);
str = dw2[k2].concat(str);
sum = 0;
}
}
if(k1==3)//小单位到千则大单位进一
{
k2++;}
}
//转换小数部分
var strdig="";
if(dig!=""){
var n = dig.charAt(0);
if(n!=0){
strdig += dw[Number(n)]+"角";//加数字
}
var n = dig.charAt(1);
if(n!=0){
strdig += dw[Number(n)]+"分";//加数字
}
}
str += "元"+strdig;
}catch(e){
return "0元";
}
return str;
}
//拆分整数与小数
function splits(tranvalue){
var value = new Array('','');
temp = tranvalue.split(".");
for(var i=0;i<temp.length;i++){
value[i] = temp[i];
}
return value;
}
var a = '12345678';
var b = transform(a);
console.log(b);
-
url加载到页面渲染的过程
从输入URL到页面加载的主干流程如下:
1、浏览器构建HTTP Request请求
2、网络传输
3、服务器构建HTTP Response 响应
4、网络传输
5、浏览器渲染页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lGlJ1tTo-1610201845189)(C:\Users\glzpcadm\AppData\Roaming\Typora\typora-user-images\1610157023577.png)]
1、应用层进行DNS解析
通过DNS将域名解析成IP地址。在解析过程中,按照
浏览器缓存
、系统缓存
、路由器缓存
、ISP(运营商)DNS缓存
、根域名服务器
、顶级域名服务器
、主域名服务器
的顺序,逐步读取缓存,直到拿到IP地址这里使用DNS预解析,可以根据浏览器定义的规则,提前解析之后可能会用到的域名,使解析结果缓存到
系统缓存
中,缩短DNS解析时间,来提高网站的访问速度2、应用层生成HTTP请求报文
接着,应用层生成针对目标WEB服务器的HTTP请求报文,HTTP请求报文包括起始行、首部和主体部分
如果访问的google.com,则起始行可能如下
GET https://www.google.com/ HTTP/1.1
首部包括域名host、keep-alive、User-Agent、Accept-Encoding、Accept-Language、Cookie等信息,可能如下 。
Host: www.google.com Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 X-Client-Data: CKm1yQEIhbbJAQijtskBCMG2yQEIqZ3KAQioo8oB Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
首部和主体内容之间有一个回车换行(CRLF),主体内容即要传输的内容。如果是get请求,则主体内容为空
3、传输层建立TCP连接
传输层传输协议分为UDP和TCP两种
UDP是无连接的协议,而TCP是可靠的有连接的协议,主要表现在三次握手:接收方会对收到的数据进行确认、发送方会重传接收方未确认的数据、接收方会将接收到数据按正确的顺序重新排序,并删除重复的数据、提供了控制拥挤的机制。
由于HTTP协议使用的是TCP协议,为了方便通信,将HTTP请求报文按序号分为多个报文段(segment),并对每个报文段进行封装。使用本地一个大于1024以上的随机TCP源端口(这里假设是1030)建立到目的服务器TCP80号端口(HTTPS协议对应的端口号是443)的连接,TCP源端口和目的端口被加入到报文段中,学名叫协议数据单元(Protocol Data Unit, PDU)。因TCP是一个可靠的传输控制协议,传输层还会加入序列号、确认号、窗口大小、校验和等参数,共添加20字节的头部信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b1WV88yW-1610201845191)(C:\Users\glzpcadm\AppData\Roaming\Typora\typora-user-images\1610157810658.png)]
TCP协议是面向连接的,所以它在开始传输数据之前需要先建立连接。要建立或初始化一个连接,两端主机必须同步双方的初始序号。同步是通过交换连接建立数据分段和初始序号来完成的,在连接建立数据分段中包含一个SYN(同步)的控制位。同步需要双方都发送自己的初始序号,并且发送确认的ACK。此过程就是三次握手
第一次握手:主机A发往主机B,主机A的初始序号是X,设置SYN位,未设置ACK位
第二次握手:主机B发往主机A,主机B的初始序号是Y,确认号(ACK)是X+1,X+1确认号暗示己经收到主机A发往主机B的同步序号。设置SYN位和ACK位
第三次握手:主机A发往主机B,主机A的序号是X+1,确认号是Y+1,Y+1确认号暗示已经收到主机B发往主机A的同步序号。设置ACK位,未设置SYN位
三次握手解决的不仅仅有序号问题,还解决了包括窗口大小、MTU(Maximum Transmission Unit,最大传输单元),以及所期望的网络延时等其他问题.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbZCsj6y-1610201845192)(C:\Users\glzpcadm\AppData\Roaming\Typora\typora-user-images\1610157881873.png)]
构建TCP请求会增加大量的网络时延,常用的优化方式如下所示
(1)资源打包,合并请求
(2)多使用缓存,减少网络传输
(3)使用keep-alive建立持久连接
(4)使用多个域名,增加浏览器的资源并发加载数,或者使用HTTP2的管道化连接的多路复用技术
4、网络层使用IP协议来选择路线
处理来自传输层的数据段segment,将数据段segment装入数据包packet,填充包头,主要就是添加源和目的IP地址,然后发送数据。在数据传输的过程中,IP协议负责选择传送的路线,称为路由功能。
5、数据链路层实现网络相邻结点间可靠的数据通信
为了保证数据的可靠传输,把数据包packet封装成帧(Frame),并按顺序传送各帧。由于物理线路的不可靠,发出的数据帧有可能在线路上出错或丢失,于是为每个数据分块计算出CRC(循环冗余检验),并把CRC添加到帧中,这样接收方就可以通过重新计算CRC来判断数据接收的正确性。一旦出错就重传
将数据包packet封装成帧(Frame),包括帧头和帧尾。帧尾是添加被称做CRC的循环冗余校验部分。帧头主要是添加数据链路层的地址,即数据链路层的源地址和目的地址,即网络相邻结点间的源MAC地址和目的MAC地址
6、物理层传输数据
数据链路层的帧(Frame)转换成二进制形式的比特(Bit)流,从网卡发送出去,再把比特转换成电子、光学或微波信号在网络中传输。
上面的6个步骤可总结为:DNS解析URL地址、生成HTTP请求报文、构建TCP连接、使用IP协议选择传输路线、数据链路层保证数据的可靠传输、物理层将数据转换成电子、光学或微波信号进行传输
网络传输
从客户机到服务器需要通过许多网络设备, 一般地,包括集线器、交换器、路由器等
【集线器】
集线器是物理层设备,比特流到达集线器后,集线器简单地对比特流进行放大,从除接收端口以外的所有端口转发出去
【交换机】
交换机是数据链路层设备,比特流到达交换机,交换机除了对比特流进行放大外,还根据源MAC地址进行学习,根据目的MAC地址进行转发。交换机根据数据帧中的目的MAC地址査询MAC地址表,把比特流从对应的端口发送出去
【路由器】
路由器是网络层设备,路由器收到比特流,转换成帧上传到数据链路层,路由器比较数据帧的目的MAC地址,如果有与路由器接收端口相同的MAC地址,则路由器的数据链路层把数据帧进行解封装,然后上传到路由器的网络层,路由器找到数据包的目的IP地址,并查询路由表,将数据从入端口转发到出端口。接着在网络层重新封装成数据包packet,下沉到数据链路层重新封装成帧frame,下沉到物理层,转换成二进制比特流,发送出去
服务器处理及反向传输
服务器接收到这个比特流,把比特流转换成帧格式,上传到数据链路层,服务器发现数据帧中的目的MAC地址与本网卡的MAC地址相同,服务器拆除数据链路层的封装后,把数据包上传到网络层。服务器的网络层比较数据包中的目的IP地址,发现与本机的IP地址相同,服务器拆除网络层的封装后,把数据分段上传到传输层。传输层对数据分段进行确认、排序、重组,确保数据传输的可靠性。数据最后被传到服务器的应用层
HTTP服务器,如nginx通过反向代理,将其定位到服务器实际的端口位置,如8080。比如,8080端口对应的是一个NodeJS服务,生成响应报文,报文主体内容是google首页的HTML页面
接着,通过传输层、网络层、数据链路层的层层封装,最终将响应报文封装成二进制比特流,并转换成其他信号,如电信号到网络中传输
浏览器渲染
客户机接受到二进制比特流之后,把比特流转换成帧格式,上传到数据链路层,客户机发现数据帧中的目的MAC地址与本网卡的MAC地址相同,拆除数据链路层的封装后,把数据包上传到网络层。网络层比较数据包中的目的IP地址,发现与本机的IP地址相同,拆除网络层的封装后,把数据分段上传到传输层。传输层对数据分段进行确认、排序、重组,确保数据传输的可靠性。数据最后被传到应用层
1、如果HTTP响应报文是301或302重定向,则浏览器会相应头中的location再次发送请求
2、浏览器处理HTTP响应报文中的主体内容,首先使用loader模块加载相应的资源
loader模块有两条资源加载路径:主资源加载路径和派生资源加载路径。主资源即google主页的index.html文件 ,派生资源即index.html文件中用到的资源
-
页面渲染css和dom的过程
浏览器渲染页面前需要先构建 DOM 和 CSSOM 树。因此,我们需要确保尽快将 HTML 和 CSS 都提供给浏览器。这也是我们为什么要在页面底部引入JavaScript代码的原因。或者说可以在头部引用,但是前提是加上async、defer,或window.onload。
dom树的渲染,首先获取原始的字节,进行字节的转化是以utf-8的格式进行转化编码成为字符,将转化完后的字节进行令牌化处理,把这些字符转化成w3c标准下的各种令牌,最后需要将发出的令牌转换成定义其属性和规则的对象。这时候才完成了dom数的渲染。
cssom数的渲染,其实也是和dom树渲染差不多,将css字节转换成字符,然后令牌化和节点化,最后链接到一个css对象模型的树结构(cssom)。
渲染阻塞吧,就是说在渲染的过程中遇见JavaScript标签的时候,会先去执行js的内容,直至脚本完成执行,然后继续构建DOM。
HTML默认是流式布局的,但CSS和JS会打破这种布局,改变DOM的外观样式以及大小和位置。 当浏览器发现布局发生了变化,这个时候就需要倒回去重新渲染,这个回退的过程叫`reflow`。
repaint
则是当我们改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变。 -
前端页面处理缓存的方法(手动删除,头文件禁止)
<METAHTTP-EQUIV="pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> <META HTTP-EQUIV="expires" CONTENT="0">
-
什么情况下能够使页面渲染加载变快(答js文件后移,css文件用链接的方式)
一、减少HTTP请求
上面说到80%~90%时间花在了下载页面中的所有组件进行的HTTP请求上。因此,改善响应时间最简单的途径就是减少HTTP请求的数量。
图片地图:
假设导航栏上有五幅图片,点击每张图片都会进入一个链接,这样五张导航的图片在加载时会产生5个HTTP请求。然而,使用一个图片地图可以提高效率,这样就只需要一个HTTP请求。
二、使用CDN
如果应用程序web服务器离用户更近,那么一个HTTP请求的响应时间将缩短。另一方面,如果组件web服务器离用户更近,则多个HTTP请求的响应时间将缩短。
CDN(内容发布网络)是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络慕课拥堵的测量。
CDN还可以进行数据备份、扩展存储能力,进行缓存,同时有助于缓和Web流量峰值压力。
CDN的缺点:
1、响应时间可能会受到其他网站流量的影响。CDN服务提供商在其所有客户之间共享Web服务器组。
2、如果CDN服务质量下降了,那么你的工作质量也将下降
3、无法直接控制组件服务器
五、将样式表放在头部
首先说明一下,将样式表放在头部对于实际页面加载的时间并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现,改善用户体验,防止“白屏”。
我们总是希望页面能够尽快显示内容,为用户提供可视化的回馈,这对网速慢的用户来说是很重要的。
将样式表放在文档底部会阻止浏览器中的内容逐步出现。为了避免当样式变化时重绘页面元素,浏览器会阻塞内容逐步呈现,造成“白屏”。这源自浏览器的行为:如果样式表仍在加载,构建呈现树就是一种浪费,因为所有样式表加载解析完毕之前务虚会之任何东西
六、将脚本放在底部
更样式表相同,脚本放在底部对于实际页面加载的时间并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现。
js的下载和执行会阻塞Dom树的构建(严谨地说是中断了Dom树的更新),所以script标签放在首屏范围内的HTML代码段里会截断首屏的内容。
下载脚本时并行下载是被禁用的——即使使用了不同的主机名,也不会启用其他的下载。因为脚本可能修改页面内容,因此浏览器会等待;另外,也是为了保证脚本能够按照正确的顺序执行,因为后面的脚本可能与前面的脚本存在依赖关系,不按照顺序执行可能会产生错误。
- 有什么方法可以延迟js文件的挂载
使用setTimeOut延迟加载, 把js外部引入的文件放到页面底部,来让js最后引入,从而加快页面加载速度
- Vue的生命周期
vue生命周期即为一个组件从出生到死亡的一个完整周期,主要包括以下4个阶段:创建,挂载,更新,销毁
创建前:beforeCreate, 创建后:created
挂载前:beforeMount, 挂载后:mounted
更新前:beforeUpdate, 更新后:updated
销毁前:beforeDestroy, 销毁后:destroyed
我平时用的比较多的钩了是created和mounted,created用于获取后台数据,mounted用于dom挂载完后做一些dom操作,以及初始化插件等.beforeDestroy用户清除定时器以及解绑事件等,
另外还新增了使用内置组件 keep-alive 来缓存实例,而不是频繁创建和销毁(开销大)
actived 实例激活
deactived 实例失效
以下为详解版,大家理解就ok:
生命周期钩子函数(11个)Function(类型),标注蓝色的那个是属于类型的意思。
beforeCreate Function 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created Function 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer), 属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el
属性目前不可见。
beforeMount Function 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted Function el 被新创建的 vm.el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el
也在文档内。
beforeUpdate Function 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
updated Function 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
activated Function keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用。
deactivated Function keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用。
beforeDestroy Function 实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
destroyed Function Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
errorCaptured(2.5.0+ 新增) (err: Error, vm: Component, info: string) => ?boolean 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
-
vue父组件和子组件生命周期的执行顺序
-
加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
注意
mounted
不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在mounted
内部使用 vm.$nextTick:mounted() { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }
-
子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
-
父组件更新过程
父 beforeUpdate -> 父 updated
-
销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
-
-
vue钩子函数的用法
-
什么时候触发vue的update(答watch和compute)
-
https了解吗,和http有什么区别
HTTPS和HTTP的主要区别
https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的;HTTPS协议是由SSL(Secure Socket Layer)/TLS (Transport Layer Security)+HTTP , 协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
-
https的加密方式,公钥和私钥的管理,证书
HTTPS加密分为两种方式:对称加密和非对称加密
对称加密是指:客户端先将加密的公钥发送给服务端;然后将按照公钥加密的密文发送到服务端,这样服务端收到公钥和密文文后就按照公钥对密文进行解密;但是在发送公钥的时候可能会被第三方截取,存在安全隐患;
非对称加密是指:客户端和服务端都有一套私钥和公钥;客户端接收到服务端的公钥后,按照公钥进行加密,将密文发送服务端后,服务端用私钥进行解密,同理,服务端接收到客户端的公钥,然后按照客户端公钥加密信息,然后发送给客户端,客户端根据自己的私钥进行解密;这样的话,客户端和服务端的私钥一直都是自己持有的,不会被第三方获取,所以比较安全;缺点是:算法复杂度比较高,导致效率低。
-
http注入有什么(答有sql的注入),怎么处理(后端减少插值处理)
csrf(跨站请求攻击),简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)
csrf防止就是加上随机token字段验证,不能加在cookie上,需要加密传输。
XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染DOM树的过程成发生了不在预期内执行的JS代码时,就发生了XSS攻击。
反射型XSS,也叫非持久型XSS,是指发生请求时,XSS代码出现在请求URL中,作为参数提交到服务器,服务器解析并响应。响应结果中包含XSS代码,最后浏览器解析并执行。
从概念上可以看出,反射型XSS代码是首先出现在URL中的,然后需要服务端解析,最后需要浏览器解析之后XSS代码才能够攻击。
XSS危害
- 通过document.cookie盗取cookie
- 使用js或css破坏页面正常的结构与样式
- 流量劫持(通过访问某段具有window.location.href定位到其他页面)
- Dos攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法用户无法得到服务器响应。
- 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作。
- 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。
XSS防御
从以上的反射型和DOM XSS攻击可以看出,我们不能原样的将用户输入的数据直接存到服务器,需要对数据进行一些处理。以上的代码出现的一些问题如下
- 没有过滤危险的DOM节点。如具有执行脚本能力的script, 具有显示广告和色情图片的img, 具有改变样式的link, style, 具有内嵌页面的iframe, frame等元素节点。
- 没有过滤危险的属性节点。如事件, style, src, href等
- 没有对cookie设置httpOnly。
如果将以上三点都在渲染过程中过滤,那么出现的XSS攻击的概率也就小很多。
sql注入就是过滤参数,尽量预编译和对输入和输出控制可http实体化编码。
1.使用参数化查询,检查变量数据类型和格式
2.采用sq语句预编译和绑定变量
3.增强SQL数据交互点的过滤处理
如不能采取使用参数化查询和预编译变量,那最好就是加强对SQL数据交互点的过滤
可参考以下关键字进行过滤:
每个提交信息的客户端页面,通过服务器端脚本(JSP、ASP、ASPX、PHP等脚本)生成的客户端页面,提交的表单(FORM)或发出的连接请求中包含的所有变量,必须对变量的值进行检查。过滤其中包含的特殊字符,或对字符进行转义处理。特殊字符包括:
SQL语句关键词:如 and 、or 、select、declare、update、xp_cmdshell,union;
sql注入的危害:
- 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露,脱取数据库中的数据内容(脱库),可获取网站管理员帐号、密码悄无声息的进行对网站后台操作等。
- 网页篡改:通过操作数据库对特定网页进行篡改,可严重影响正常业务进行。
- 网站被挂马:将恶意文件写入数据库,修改数据库字段值,嵌入网马链接,进行挂马攻击。
- 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
- 文件系统操作:列取目录、读取、写入shell文件获取webshell,远程控制服务器,安装后门,经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
- 执行系统命令:远程命令执行,可破坏硬盘数据,瘫痪全系统。
-
Http2.0
参考:https://www.cnblogs.com/liuwd/p/10869103.html
HTTP/2主要是为了解决现HTTP 1.1性能不好的问题才出现的。 大幅度提升web性能,减少网络延迟。
http2特点:
2.1 多路复用
多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。
也就是说一个TCP连接可以一次发送和接受多个请求拉。
这样实际上就避免了突发性和短时性的HTTP连接性能差的问题了(因为TCP协议里面有慢启动,开始都很慢的).
2.2 二进制分帧
就是多加了一层,专门将消息分成了更小的二进制编码的帧。减少了传输量。
2.3 首部压缩
新的压缩算法,减小首部大小,提升发送效率。
2.4 服务推送
客户端请求一个资源,服务端把客户端可能需要请求的其他资源一起主动发给它,减少了交互次数。另外服务端还能缓存这样的资源,提升效率
-
如何处理表单提交过程中因为网络问题多次点击的事件(用防抖和节流的思想回答了下,不会)
-
js防抖与节流了解吗,怎么实现?(手写防抖代码,太难了)
函数防抖
1、理解:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
2、思路:每次触发事件时都取消之前的延时调用方法function debounce(fn) { let timeout = null; // 创建一个标记用来存放定时器的返回值 return function () { clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 fn.apply(this, arguments); }, 500); }; } function sayHi() { console.log('防抖成功'); } var inp = document.getElementById('inp'); inp.addEventListener('input', debounce(sayHi)); // 防抖
函数节流
1、理解:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
2、解释:每次触发事件时都判断当前是否有等待执行的延时函数
3、实现:
function throttle(fn) { let canRun = true; // 通过闭包保存一个标记 return function () { if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return canRun = false; // 立即设置为false setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中 fn.apply(this, arguments); // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉 canRun = true; }, 500); }; } function sayHi(e) { console.log(e.target.innerWidth, e.target.innerHeight); } window.addEventListener('resize', throttle(sayHi));
防抖和节流的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次,而节流的 情况会每隔一定时间(参数wait)调用函数。
-
项目中用了webSocket,怎么实现的,有什么优点
Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说
-
除了webSocket,有了解其他的即时通信框架吗(不会)
-
css问题:如何实现两栏布局?
侧边栏左浮动+正文部分overflow:auto
代码部分
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrap{ width:900px; margin:0 auto; } .left{ width: 200px; height: 500px; background: #ccffff; float: left; } .right{ height: 500px; overflow: auto; background: #ffcccc; } </style> </head> <body> <div class="wrap"> <aside class="left"></aside> <div class="right"> 这里是正文!这里是正文!这里是正文!这里是正文!这里是正文!这里是正文! </div> </div> </body> </html>
定位实现两栏布局
代码部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrap{ width:900px; margin:0 auto; position: relative; } .left{ width:200px; height:500px; background: #ccffff; position: absolute; top:0; left:0; } .right{ width:700px; height:500px; background: #ffcccc; position: absolute; top:0; right:0; } </style> </head> <body> <div class="wrap"> <aside class="left"></aside> <div class="right"> 这里是正文!这里是正文!这里是正文!这里是正文!这里是正文!这里是正文! </div> </div> </body> </html>
纯浮动形式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrap{ width:900px; margin:0 auto; overflow: hidden; } .left{ width:200px; height:500px; background: #ccffff; float: left; } .right{ width:700px; height:500px; background: #ffcccc; float: left; } </style> </head> <body> <div class="wrap"> <aside class="left"></aside> <div class="right"> 这里是正文!这里是正文!这里是正文!这里是正文!这里是正文!这里是正文! </div> </div> </body> </html>
浮动+常规流
代码部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .wrap{ margin:0 auto; width:80%; } .left{ width:200px; height:500px; background: #ccffff; float: left; } .right{ height: 500px; background: #ffcccc; margin-left:200px; </style> </head> <body> <div class="wrap"> <aside class="left"></aside> <div class="right"> 这里是正文!这里是正文!这里是正文!这里是正文!这里是正文!这里是正文! </div> </div> </body> </html>
-
Tcp和udp,简单说一下,什么时候用udp
1.基于连接与无连接 TCP(传输控制协议)是面向连接的协议。也就是说,在收发数据前,必须和对方建立可靠的连接。一个 TCP 连接必须要经过三次“对话”才能建立起来(确保双方都可进行信息的收发),而断开连接要进行四次挥手。面向连接的通信方式,大大提高了数据通信的可靠性,使发送数据端和接收端在数据正式传输前就有了交互,为数据正式传输打下了可靠的基础。 UDP 是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上
2.TCP 可靠,UDP 不可靠 UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数) TCP 数据确认,顺序控制,和重发机制:ACK 是 TCP 报头的控制位之一,对数据进行确认。如确认号为 X,则表示前 X-1 个数据段都收到了,只有当 ACK=1 时,确认号才有效,当 ACK=0 时,确认号无效,这时会要求重传数据,保证数据的完整性和正确性。
3.流模式与数据报模式 UDP 是面向报文的。发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付给 IP 层。既不拆分,也不合并 TCP 采取流控制(流量控制),可以分多次发送/接收,但是,发送的数据量不能大于对方的接收缓存(流量控制),如果硬是要发送过量数据,则对方的缓存满了就会把多出的数据丢弃。 *TCP 拥塞控制 *
4.快速 UDP 信息包的标题很短,只有 8 个字节,相对于 TCP 的 20 个字节信息包的额外开销很小。 UDP 传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制 UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话,实时视频会议等),但网络拥塞时有些报文可能会丢失(所以不可靠)
5.由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
tcp和udp的区别,简单来说, tcp是有序可靠传输, 而udp是不可靠乱序传输,但是实际上你把udp看做IP可能更准确一点,因为可以在udp基础上开发出可靠udp等各种传输.
它的兼容性是跨平台的,也就是,只要你选择的是tcp,那么不管是windows还是linux,unix,只要支持tcp/ip,那么就可以保证实现可靠连接和传输.
udp是比tcp更接近IP的协议, 通常udp是不可靠传输,但是我们可以在应用层对udp加上校验和序列号,做成可靠传输,这一点不可不知.
[1] 如果数据要求完整,不允许任何错误发生
[A] 应用层协议开放模式 [例如http ftp]
建议选择tcp,几乎是唯一选择.
[B] 应用曾协议封闭模式 [例如游戏]
(1) 大量连接
[a] 长连接
[一] 少量数据传输
优先考虑可靠udp传输 , tcp建议在20000连接以下使用.
[二] 大流量数据传输
只有在10000连接以下可以考虑tcp , 其他情况优先使用udp可靠传输
[b] 短连接
[一] 少量数据传输
建议使用udp标准模式, 加入序列号, 如果连接上限不超2万,可以考虑tcp
[二] 大流量数据传输
10000连接以下考虑tcp ,其他情况使用udp可靠传输
在遇到海量连接的情况下,建议优先考虑udp可靠传输,使用tcp,由于tcp/ip栈的链表实现的影响,连接越多,性能下降越快,而udp可以实现队列,是一条平滑的直线,几乎没有性能影响.
(2) 有限连接 [通常小于2000 , 一般每服务器为几百到1000左右]
[a] 长连接
除非有数据的实时性要求,优先考虑tcp,否则使用udp可靠传输.
[b] 短连接
优先考虑tcp.
在有限连接的情况下,使用tcp可以减少代码的复杂性,增加广泛的移植性,并且不需要考虑性能问题.
[2] 允许丢包,甚至可以乱序
[a] 对实时性要求比较高,例如voip , 那么udp是最优选择.
[b] 部分数据允许丢包,部分数据要求完整,部分有实时性要求,通常这样的需求是出现在游戏里, 这时候, 基于udp协议改造的udp多路可靠传输[同时支持不可靠模式],基本是唯一能满足的,当然也可以使用tcp来传输要求完整的数据,但是通常不建议,因为同时使用tcp和udp传输数据,会导致代码臃肿复杂度增加,udp可靠传输完全可以替代tcp.
[c]部分数据优先传输,部分可丢弃数据在规定时效内传输, 这通常是实时视频流, 在有限连接模式下,可以考虑tcp+udp , 但是通常, 可靠udp传输是最好的选择.
-
算法题:分层电费计价(函数拓展不行)
-
算法题:字符串数组最长的前缀
var arr = ["dadaswower", "dadasdaw", "dadaswower"];
let fn = () => {
for (let i = 0; i < arr[0].length; i++) {
for (let s = 0; s < arr.length; s++) {
if (s + 1 < arr.length) {
if (arr[s][i] != arr[s + 1][i]) {
return i;
}
}
}
}
}
var str = fn() === undefined ? arr[0] : arr[0].substr(0,fn());
console.log(str);//dadas
vue组件通信、事件总线(具体怎么实现的)、vuex的实现、
浏览器缓存、
htt状态码、
promise.all手写、
this指向、
看图回答输出、
编程题 90度翻转数组。
2、讲讲csrf、xss攻击
3、vue的双向绑定的原理?
4、http缓存有哪些?
HTTP缓存的分类
根据是否需要重新向服务器发起请求来分类,可分为(强制缓存,协商缓存) 根据是否可以被单个或者多个用户使用来分类,可分为(私有缓存,共享缓存) 强制缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。下面是强制缓存和协商缓存的一些对比:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vTYHiBMl-1610201845197)(C:\Users\glzpcadm\AppData\Roaming\Typora\typora-user-images\1610199121539.png)]
5、为什么vue里面,组件的data需要返回一个函数?
组件是可复用的`vue`实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的`data`数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,`data`数据就应该被复制一次,之后,当某一处复用的地方组件内`data`数据被改变时,其他复用地方组件的`data`数据不受影响。
6、箭头函数和普通函数的区别?
箭头函数有两种格式,一种只包含一个表达式,连{ … }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ … }和return。
箭头函数是匿名函数,不能作为构造函数,不能使用new
箭头函数不绑定arguments,取而代之用扩展运算符…解决
箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
箭头函数没有原型属性
var a = ()=>{
return 1;
}
function b(){
return 2;
}
console.log(a.prototype); // undefined
console.log(b.prototype); // {constructor: ƒ}
箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
let obj2 = {
a: 10,
b: function(n) {
let f = (n) => n + this.a;
return f(n);
},
c: function(n) {
let f = (n) => n + this.a;
let m = {
a: 20
};
return f.call(m,n);
}
};
console.log(obj2.b(1)); // 11
console.log(obj2.c(1)); // 11
7、用过webpack吗?在项目中怎么配置?图片文件需要怎么配置?
url-loader进行图片处理
{test:/.(jpg|png|gif|bmp|jpeg)$/,use:‘url-loader?limit=8908&name=[hash:8]-[name].[ext]’},
8、编程题:
1)实现一个fibonacci函数,输入数字n,输出fibonacci数列的第n项数字,并给该函数加入缓存功能。
这里用动态规划来实现会简单一些,但是题目要求有缓存功能
function fibonacci(n, map = {
}){
if(n == 1 || n == 2){
map[n] = 1;
return 1;
}
if(!map[n]){
map[n] = fibonacci(n-1, map) + fibonacci(n-2, map)
}
return map[n];
}
2)给定一个字符串str,只会出现{}()[]这六种字符,请实现一个函数isMatch(str)判断这个字符串中的括号是否是匹配的。
例如以下字符串均为括号匹配的:(){
{}[]} {}([])
以下字符串不为括号匹配: ({} ([)[{}
这题用栈的思想很容易解
function isMatch(str){
let stack = [];
for(let i=0;i<str.length;i++){
if(str[i] == '(' || str[i] == '{' || str[i] == '['){
stack.push(str[i])
}else if(str[i] == ')' || str[i] == '}' || str[i] == ']'){
let target = stack[stack.length-1];
if(
target == '(' && str[i] == ')' ||
target == '{' && str[i] == '}' ||
target == '[' && str[i] == ']'
){
stack.pop();
}else{
return false;
}
}
}
return !stack.length
}
实现一个函数,返回一个n,m的随机数。
Math.random,要注意的是Math.random返回的是0到1之间的随机数,包括0但是不包括1。
vue的nexttick
this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
vuex
1 vuex有哪几种状态和属性
有五种,分别是 State、 Getter、Mutation 、Action、 Module (就是mapAction等)
vuex的流程
页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation。mutation会修改state中对于的值。
最后通过getter把对应值跑出去,在页面的计算属性中,通过mapGetter来动态获取state中的值
2 vuex的State特性是?
stae就是存放数据的地方,类似一个仓库
特性就是当mutation修改了state的数据的时候,他会动态的去修改所有的调用这个变量的所有组件里面的值( 若是store中的数据发生改变,依赖这个数据的组件也会发生更新 )
3 vuex的Getter特性是?
getter用来获取数据,mapgetter经常在计算属性中被使用
4 vuex的Mutation特性是?
一、Action 类似于 mutation,不同在于:
二、Action 提交的是 mutation,而不是直接变更状态。
三、Action 可以包含任意异步操作
5 vuex的优势
1 状态管理工具 核心是响应式的做到数据管理
一个页面发生数据变化。动态的改变对应的页面
相比使用localStorage ,localstorge只能纯属字符串数据格式,因此还得封装自己的写入写出,localstorage的优势是永久存储
promise
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。 get post区别及应用场景
浏览器缓存
// 手写Promise.all()
Promise.property.all = function (iterators) {
const promises = Array.from(iterators);
const len = promises.length;
let count = 0;
let resultList = [];
return new Promise((resolve,reject)=>{
promises.forEach((p,index) =>{
Promise.resolve(p)
.then((result)=>{
count++;
resultList[index] = result;
if(count === len){
resolve(resultList);
}
})
.catch(e=>{
reject(e);
})
})
})
}
手写一个promise
// 首先要明确Promise是一个类,所以我们用class声明。
// 其次,构造函数中接收一个executor,它有两个参数,一个是resolve,一个是reject
// 这里要注意,resolve和reject都是函数
class Promise(){
// 构造函数(入参是执行器,包括resolve和reject两个函数)
constructor(executor){
// 必要的初始化,这里用到状态,值和原因三个变量
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 定义成功函数,入参是value
let resolve = value => {
// 首先要判断state是否为等待态,如果不是则不做任何处理
if(this.state === 'pending'){
// 修改状态
this.state = 'fulfilled';
// 更新值
this.value = value;
}
};
// 定义失败函数,入参是失败原因
let reject = reason => {
// 同样的逻辑
if(this.state === 'pending'){
this.state = 'rejected';
this.reason = reason;
}
};
// 这是promise对象的的主逻辑,执行executor,如果执行器出错,则捕获错误后执行reject函数
try{
executor(resolve, reject);
}catch(err){
reject(err);
}
}
// 定义Promise的then函数
// then方法接收两个参数,如果状态为fulfilled,执行onFulfilled
// 如果状态为rejected,则执行onRejected
then(onFulfilled, onRejected){
if(this.state === 'fulfilled'){
onFulfilled(this.value);
};
if(this.state === 'rejected'){
onRejected(this.reason);
};
}
}
复制代码
= result;
if(count === len){
resolve(resultList);
}
})
.catch(e=>{
reject(e);
})
})
})
}
手写一个promise
```js
// 首先要明确Promise是一个类,所以我们用class声明。
// 其次,构造函数中接收一个executor,它有两个参数,一个是resolve,一个是reject
// 这里要注意,resolve和reject都是函数
class Promise(){
// 构造函数(入参是执行器,包括resolve和reject两个函数)
constructor(executor){
// 必要的初始化,这里用到状态,值和原因三个变量
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 定义成功函数,入参是value
let resolve = value => {
// 首先要判断state是否为等待态,如果不是则不做任何处理
if(this.state === 'pending'){
// 修改状态
this.state = 'fulfilled';
// 更新值
this.value = value;
}
};
// 定义失败函数,入参是失败原因
let reject = reason => {
// 同样的逻辑
if(this.state === 'pending'){
this.state = 'rejected';
this.reason = reason;
}
};
// 这是promise对象的的主逻辑,执行executor,如果执行器出错,则捕获错误后执行reject函数
try{
executor(resolve, reject);
}catch(err){
reject(err);
}
}
// 定义Promise的then函数
// then方法接收两个参数,如果状态为fulfilled,执行onFulfilled
// 如果状态为rejected,则执行onRejected
then(onFulfilled, onRejected){
if(this.state === 'fulfilled'){
onFulfilled(this.value);
};
if(this.state === 'rejected'){
onRejected(this.reason);
};
}
}
复制代码
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/145712.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...