UDP协定为什么不牢靠?
UDP在传输数据之前不须要先建设连贯,远地主机的运输层在接管到UDP报文后,不须要确认,提供不牢靠交付。总结就以下四点:
- 不保障音讯交付:不确认,不重传,无超时
- 不保障交付程序:不设置包序号,不重排,不会产生队首阻塞
- 不跟踪连贯状态:不用建设连贯或重启状态机
- 不进行拥塞管制:不内置客户端或网络反馈机制
浏览器是如何对 HTML5 的离线贮存资源进行治理和加载?
- 在线的状况下,浏览器发现 html 头部有 manifest 属性,它会申请 manifest 文件,如果是第一次拜访页面 ,那么浏览器就会依据 manifest 文件的内容下载相应的资源并且进行离线存储。如果曾经拜访过页面并且资源曾经进行离线存储了,那么浏览器就会应用离线的资源加载页面,而后浏览器会比照新的 manifest 文件与旧的 manifest 文件,如果文件没有产生扭转,就不做任何操作,如果文件扭转了,就会从新下载文件中的资源并进行离线存储。
- 离线的状况下,浏览器会间接应用离线存储的资源。
说一下类组件和函数组件的区别?
1. 语法上的区别:函数式组件是一个纯函数,它是须要承受props参数并且返回一个React元素就能够了。类组件是须要继承React.Component的,而且class组件须要创立render并且返回React元素,语法上来讲更简单。2. 调用形式函数式组件能够间接调用,返回一个新的React元素;类组件在调用时是须要创立一个实例的,而后通过调用实例里的render办法来返回一个React元素。3. 状态治理函数式组件没有状态治理,类组件有状态治理。4. 应用场景类组件没有具体的要求。函数式组件个别是用在大型项目中来宰割大组件(函数式组件不必创立实例,所有更高效),个别状况下能用函数式组件就不必类组件,晋升效率。复制代码
Set 和 Map有什么区别?
1、Map是键值对,Set是值得汇合,当然键和值能够是任何得值2、Map能够通过get办法获取值,而set不能因为它只有值3、都能通过迭代器进行for...of 遍历4、Set的值是惟一的能够做数组去重,而Map因为没有格局限度,能够做数据存储复制代码
说一说js是什么语言
JavaScript是一种直译式脚本语言,是一种动静类型、弱类型、基于原型的语言,内置反对类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,宽泛用于客户端的脚本语言,最早是在HTML(规范通用标记语言下的一个利用)网页上应用,用来给HTML网页减少动静性能。js语言是弱语言类型, 因而咱们在我的项目开发中当咱们随便更该某个变量的数据类型后有可能会导致其余援用这个变量的办法中报错等等。复制代码
说说浏览器缓存
缓存能够缩小网络 IO 耗费,进步访问速度。浏览器缓存是一种操作简略、效果显著的前端性能优化伎俩很多时候,大家偏向于将浏览器缓存简略地了解为“HTTP 缓存”。但事实上,浏览器缓存机制有四个方面,它们依照获取资源时申请的优先级顺次排列如下:Memory CacheService Worker CacheHTTP CachePush Cache缓存它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的状况下,才会走协商缓存 实现强缓存,过来咱们始终用 expires。 当服务器返回响应时,在 Response Headers 中将过期工夫写入 expires 字段,当初个别应用Cache-Control 两者同时呈现应用Cache-Control 协商缓存,Last-Modified 是一个工夫戳,如果咱们启用了协商缓存,它会在首次申请时随着 Response Headers 返回:每次申请去判断这个工夫戳是否发生变化。 从而去决定你是304读取缓存还是给你返回最新的数据复制代码
原型
构造函数是一种非凡的办法,次要用来在创建对象时初始化对象。每个构造函数都有prototype(原型)(箭头函数以及Function.prototype.bind()没有)属性,这个prototype(原型)属性是一个指针,指向一个对象,这个对象的用处是蕴含特定类型的所有实例共享的属性和办法,即这个原型对象是用来给实例对象共享属性和办法的。每个实例对象的__proto__都指向这个构造函数/类的prototype属性。面向对象的三大个性:继承/多态/封装对于new操作符:1. new执行的函数, 函数外部默认生成了一个对象2. 函数外部的this默认指向了这个new生成的对象3. new执行函数生成的这个对象, 是函数的默认返回值ES5例子:function Person(obj) { this.name = obj.name this.age= obj.age}// 原型办法Person.prototype.say = function() { console.log('你好,', this.name )}// p为实例化对象,new Person()这个操作称为构造函数的实例化let p = new Person({name: '番茄', age: '27'})console.log(p.name, p.age)p.say()ES6例子:class Person{ constructor(obj) { this.name = obj.name this.age= obj.age } say() { console.log(this.name) }}let p = new Person({name: 'ES6-番茄', age: '27'})console.log(p.name, p.age)p.say()复制代码
webpack配置入口进口
module.exports={ //入口文件的配置项 entry:{}, //进口文件的配置项 output:{}, //模块:例如解读CSS,图片如何转换,压缩 module:{}, //插件,用于生产模版和各项性能 plugins:[], //配置webpack开发服务性能 devServer:{}}简略形容了一下这几个属性是干什么的。形容一下npm run dev / npm run build执行的是哪些文件通过配置proxyTable来达到开发环境跨域的问题,而后又能够扩大和他聊聊跨域的产生,如何跨域最初能够在聊聊webpack的优化,例如babel-loader的优化,gzip压缩等等复制代码
说一下vue3.0你理解多少?
<!-- 响应式原理的扭转 Vue3.x 应用Proxy取代 Vue2.x 版本的Object.defineProperty --> <!-- 组件选项申明形式Vue3.x 应用Composition API setup 是Vue3.x新增的一个选项,他 是组件内应用Composition API 的入口 --> <!-- 模板语法变动slot具名插槽语法 自定义指令 v-model 降级 --> <!-- 其它方面的更改Suspense反对Fragment(多个根节点) 和Protal (在dom其余局部渲染组建内容)组件 针对一些非凡的场景做了解决。基于treeshaking优化,提供了更多的内置性能。 -->复制代码
你在工作终于到那些问题,解决办法是什么
常常遇到的问题就是Cannot read property ‘prototype’ of undefined解决办法通过浏览器报错提醒代码定位问题,解决问题Vue我的项目中遇到视图不更新,办法不执行,埋点不触发等问题个别解决方案查看浏览器报错,查看代码运行到那个阶段未之行完结,浏览源码以及相干文档等而后举进去最近开发的我的项目中遇到的算是两个比拟大的问题。复制代码
说一下data为什么是一个函数而不是一个对象?
JavaScript中的对象是援用类型的数据,当多个实例援用同一个对象时,只有一个实例对这个对象进行操作,其余实例中的数据也会发生变化。而在Vue中,咱们更多的是想要复用组件,那就须要每个组件都有本人的数据,这样组件之间才不会互相烦扰。所以组件的数据不能写成对象的模式,而是要写成函数的模式。数据以函数返回值的模式定义,这样当咱们每次复用组件的时候,就会返回一个新的data,也就是说每个组件都有本人的公有数据空间,它们各自保护本人的数据,不会烦扰其余组件的失常运行。
说一下常见的git操作
git branch 查看本地所有分支git status 查看以后状态 git commit 提交 git branch -a 查看所有的分支git branch -r 查看近程所有分支git commit -am "nit" 提交并且加正文 git remote add origin git@192.168.1.119:ndshowgit push origin master 将文件给推到服务器上 git remote show origin 显示近程库origin里的资源 git push origin master:developgit push origin master:hb-dev 将本地库与服务器上的库进行关联 git checkout --track origin/dev 切换到近程dev分支git branch -D master develop 删除本地库developgit checkout -b dev 建设一个新的本地分支devgit merge origin/dev 将分支dev与以后分支进行合并git checkout dev 切换到本地dev分支git remote show 查看近程库git add .git rm 文件名(包含门路) 从git中删除指定文件git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来git config --list 看所有用户git ls-files 看曾经被提交的git rm [file name] 删除一个文件git commit -a 提交以后repos的所有的扭转git add [file name] 增加一个文件到git indexgit commit -v 当你用-v参数的时候能够看commit的差别git commit -m "This is the message describing the commit" 增加commit信息git commit -a -a是代表add,把所有的change加到git index里而后再commitgit commit -a -v 个别提交命令git log 看你commit的日志git diff 查看尚未暂存的更新git rm a.a 移除文件(从暂存区和工作区中删除)git rm --cached a.a 移除文件(只从暂存区中删除)git commit -m "remove" 移除文件(从Git中删除)git rm -f a.a 强行移除批改后文件(从暂存区和工作区中删除)git diff --cached 或 $ git diff --staged 查看尚未提交的更新git stash push 将文件给push到一个长期空间中git stash pop 将文件从长期空间pop下来
webpack3和webpack4区别
1.modewebpack减少了一个mode配置,只有两种值development | production。对不同的环境他会启用不同的配置。2.CommonsChunkPluginCommonChunksPlugin曾经从webpack4中移除。可应用optimization.splitChunks进行模块划分(提取专用代码)。然而须要留神一个问题,默认配置只会对异步申请的模块进行提取拆分,如果要对entry进行拆分须要设置optimization.splitChunks.chunks = 'all'。3.webpack4应用MiniCssExtractPlugin取代ExtractTextWebpackPlugin。4.代码宰割。应用动静import,而不是用system.import或者require.ensure5.vue-loader。应用vue-loader插件为.vue文件中的各局部应用绝对应的loader,比方css-loader等6.UglifyJsPlugin当初也不须要应用这个plugin了,只须要应用optimization.minimize为true就行,production mode上面主动为trueoptimization.minimizer能够配置你本人的压缩程序复制代码
New操作符做了什么事件?
1、首先创立了一个新对象2、设置原型,将对象的原型设置为函数的prototype对象3、让函数的this指向这个对象,执行构造函数的代码(为这个新对象增加属性)4、判断函数的返回值类型,如果是值类型,返回创立的对象。如果是援用类型,就返回这个援用类型的对象复制代码
JS闭包,你理解多少?
应该有面试官问过你:
- 什么是闭包?
- 闭包有哪些理论使用场景?
- 闭包是如何产生的?
- 闭包产生的变量如何被回收?
这些问题其实都能够被看作是同一个问题,那就是面试官在问你:你对JS闭包理解多少?
来总结一下我听到过的答案,尽量齐全还原候选人面试的时候说的原话。
答案1:
就是一个function
外面return
了一个子函数,子函数拜访了里面那个函数的变量。
答案2:
for循环外面能够用闭包来解决问题。
for(var i = 0; i < 10; i++){ setTimeout(()=>console.log(i),0)}// 控制台输入10遍10.for(var i = 0; i < 10; i++){ (function(a){ setTimeout(()=>console.log(a),0) })(i)} // 控制台输入0-9复制代码
答案3:
以后作用域产产生了对父作用域的援用。
答案4:
不晓得。是跟浏览器的垃圾回收机制无关吗?
开杠了。请问,小伙伴的答案和以上的内容有多少类似水平?
其实,拿着这些问题好好想想,你就会发现这些问题都只是为了最终那一个问题。
闭包的底层实现原理
1. JS执行上下文
咱们都晓得,咱们手写的js代码是要通过浏览器V8进行预编译后能力真正的被执行。例如变量晋升、函数晋升。举个栗子。
// 栗子:var d = 'abc';function a(){ console.log("函数a");};console.log(a); // ƒ a(){ console.log("函数a"); }a(); // '函数a'var a = "变量a"; console.log(a); // '变量a'a(); // a is not a functionvar c = 123;// 输入后果及程序:// ƒ a(){ console.log("函数a"); }// '函数a'// '变量a'// a is not a function// 栗子预编后相当于:function a(){ console.log("函数a");};var d;console.log(a); // ƒ a(){ console.log("函数a"); }a(); // '函数a'a = "变量a"; // 此时变量a赋值,函数申明被笼罩console.log(a); // "变量a"a(); // a is not a function复制代码
那么问题来了。 请问是谁来执行预编译操作的?那这个谁又是在哪里进行预编译的?
是的,你的纳闷没有错。js代码运行须要一个运行环境,那这个环境就是执行上下文。 是的,js运行前的预编译也是在这个环境中进行。
js执行上下文分三种:
全局执行上下文
: 代码开始执行时首先进入的环境。函数执行上下文
:函数调用时,会开始执行函数中的代码。eval执行上下文
:不倡议应用,可疏忽。
那么,执行上下文的周期,分为两个阶段:
创立阶段
- 创立词法环境
- 生成变量对象(
VO
),建设作用域链、作用域链、作用域链(重要的事说三遍) - 确认
this
指向,并绑定this
执行阶段
。这个阶段进行变量赋值,函数援用及执行代码。
你当初猜猜看,预编译是产生在什么时候?
噢,我遗记说了,其实与编译还有另一个称说:执行期上下文
。
预编译产生在函数执行之前。预编译四部曲为:
- 创立
AO
对象 - 找形参和变量申明,将变量和形参作为AO属性名,值为
undefined
- 将实参和形参相对立
- 在函数体里找到函数申明,值赋予函数体。最初程序输入变量值的时候,就是从
AO
对象中拿。
所以,预编译真正的后果是:
var AO = { a = function a(){console.log("函数a");}; d = 'abc'}复制代码
咱们从新来。
1. 什么叫变量对象?
变量对象是 js
代码在进入执行上下文时,js
引擎在内存中建设的一个对象,用来寄存以后执行环境中的变量。
2. 变量对象(VO)的创立过程
变量对象的创立,是在执行上下文创立阶段,顺次通过以下三个过程:
创立
arguments
对象。对于函数执行环境,首先查问是否有传入的实参,如果有,则会将参数名是实参值组成的键值对放入
arguments
对象中。否则,将参数名和undefined
组成的键值对放入arguments
对象中。
//举个栗子 function bar(a, b, c) { console.log(arguments); // [1, 2] console.log(arguments[2]); // undefined}bar(1,2)复制代码
- 当遇到同名的函数时,前面的会笼罩后面的。
console.log(a); // function a() {console.log('Is a ?') }function a() { console.log('Is a');}function a() { console.log('Is a ?')}/**ps: 在执行第一行代码之前,函数申明曾经创立实现.前面的对之前的申明进行了笼罩。**/复制代码
- 查看以后环境中的变量申明并赋值为
undefined
。当遇到同名的函数申明,为了防止函数被赋值为undefined
,会疏忽此申明
console.log(a); // function a() {console.log('Is a ?') }console.log(b); // undefinedfunction a() { console.log('Is a ');}function a() {console.log('Is a ?');}var b = 'Is b';var a = 10086;/**这段代码执行一下,你会发现 a 打印后果仍旧是一个函数,而 b 则是 undefined。**/复制代码
依据以上三个步骤,对于变量晋升也就晓得是怎么回事了。
3. 变量对象变为流动对象
执行上下文的第二个阶段,称为执行阶段,在此时,会进行变量赋值,函数援用并执行其余代码,此时,变量对象变为流动对象。
咱们还是举下面的例子:
console.log(a); // function a() {console.log('fjdsfs') }console.log(b); // undefinedfunction a() { console.log('Is a');}function a() { console.log('Is a?');}var b = 'Is b';console.log(b); // 'Is b'var a = 10086; console.log(a); // 10086var b = 'Is b?';console.log(b); // 'Is b?'复制代码
在下面的代码中,代码真正开始执行是从第一行 console.log() 开始的,自这之前,执行上下文是这样的:
// 创立过程EC= { VO: {}; // 创立变量对象 scopeChain: {}; // 作用域链}VO = { argument: {...}; // 以后为全局上下文,所以这个属性值是空的 a: <a reference> // 函数 a 的援用地址 b: undefiend // 见上文创立变量对象的第三步}复制代码
词法作用域(Lexical scope
)
这里想阐明,咱们在函数执行上下文中有变量,在全局执行上下文中有变量。JavaScript
的一个简单之处在于它如何查找变量,如果在函数执行上下文中找不到变量,它将在调用上下文中寻找它,如果在它的调用上下文中没有找到,就始终往上一级,直到它在全局执行上下文中查找为止。(如果最初找不到,它就是 undefined
)。
再来举个栗子:
1: let top = 0; // 2: function createWarp() { 3: function add(a, b) { 4: let ret = a + b 5: return ret 6: } 7: return add 8: } 9: let sum = createWarp()10: let result = sum(top, 8)11: console.log('result:',result)复制代码
剖析过程如下:
- 在全局上下文中申明变量
top
并赋值为0. - 2 - 8行。在全局执行上下文中申明了一个名为
createWarp
的变量,并为其调配了一个函数定义。其中第3-7行形容了其函数定义,并将函数定义存储到那个变量(createWarp
)中。 - 第9行。咱们在全局执行上下文中申明了一个名为
sum
的新变量,临时,值为undefined
。 - 第9行。遇到
()
,表明须要执行或调用一个函数。那么查找全局执行上下文的内存并查找名为createWarp
的变量。 显著,曾经在步骤2中创立结束。接着,调用它。 - 调用函数时,回到第2行。创立一个新的
createWarp
执行上下文。咱们能够在createWarp
的执行上下文中创立自有变量。js
引擎createWarp
的上下文增加到调用堆栈(call stack
)。因为这个函数没有参数,间接跳到它的主体局部. - 3 - 6 行。咱们有一个新的函数申明,在
createWarp
执行上下文中创立一个变量add
。add
只存在于createWarp
执行上下文中, 其函数定义存储在名为add
的自有变量中。 - 第7行,咱们返回变量
add
的内容。js引擎查找一个名为add
的变量并找到它. 第4行和第5行括号之间的内容形成该函数定义。 createWarp
调用结束,createWarp
执行上下文将被销毁。add 变量也跟着被销毁。 但add
函数定义依然存在,因为它返回并赋值给了sum
变量。 (ps:这才是闭包产生的变量存于内存当中的假相
)- 接下来就是简略的执行过程,不再赘述。。
- ……
- 代码执行结束,全局执行上下文被销毁。sum 和 result 也跟着被销毁。
小结一下
当初,如果再让你答复什么是闭包,你能答出多少?
其实,大家说的都对。不论是函数返回一个函数,还是产生了内部作用域的援用,都是有情理的。
所以,什么是闭包?
- 解释一下作用域链是如何产生的。
- 解释一下js执行上下文的创立、执行过程。
- 解释一下闭包所产生的变量放在哪了。
- 最初请把以上3点联合起来说给面试官听。
深拷贝浅拷贝
浅拷贝:浅拷贝通过ES6新个性Object.assign()或者通过扩大运算法...来达到浅拷贝的目标,浅拷贝批改正本,不会影响原数据,但毛病是浅拷贝只能拷贝第一层的数据,且都是值类型数据,如果有援用型数据,批改正本会影响原数据。深拷贝:通过利用JSON.parse(JSON.stringify())来实现深拷贝的目标,但利用JSON拷贝也是有毛病的,当要拷贝的数据中含有undefined/function/symbol类型是无奈进行拷贝的,当然咱们想我的项目开发中须要深拷贝的数据个别不会含有以上三种类型,如有须要能够本人在封装一个函数来实现。复制代码
说一下你对盒模型的了解?
CSS3中的盒模型有以下两种:规范盒模型、IE盒模型盒模型都是由四个局部组成的,别离是margin、border、padding和content规范盒模型和IE盒模型的区别在于设置width和height时, 所对应的范畴不同1、规范盒模型的width和height属性的范畴只蕴含了content2、IE盒模型的width和height属性的范畴蕴含了border、padding和content能够通过批改元素的box-sizing属性来扭转元素的盒模型;1、box-sizing:content-box示意规范盒模型(默认值)2、box-sizing:border-box示意IE盒模型(怪异盒模型)复制代码
CDN的作用
CDN个别会用来托管Web资源(包含文本、图片和脚本等),可供下载的资源(媒体文件、软件、文档等),应用程序(门户网站等)。应用CDN来减速这些资源的拜访。
(1)在性能方面,引入CDN的作用在于:
- 用户收到的内容来自最近的数据中心,提早更低,内容加载更快
- 局部资源申请调配给了CDN,缩小了服务器的负载
(2)在平安方面,CDN有助于进攻DDoS、MITM等网络攻击:
- 针对DDoS:通过监控剖析异样流量,限度其申请频率
- 针对MITM:从源服务器到 CDN 节点到 ISP(Internet Service Provider),全链路 HTTPS 通信
除此之外,CDN作为一种根底的云服务,同样具备资源托管、按需扩大(可能应答流量顶峰)等方面的劣势。
代码输入后果
Promise.resolve().then(() => { return new Error('error!!!')}).then(res => { console.log("then: ", res)}).catch(err => { console.log("catch: ", err)})复制代码
输入后果如下:
"then: " "Error: error!!!"复制代码
返回任意一个非 promise 的值都会被包裹成 promise 对象,因而这里的return new Error('error!!!')
也被包裹成了return Promise.resolve(new Error('error!!!'))
,因而它会被then捕捉而不是catch。
Vuex有哪些根本属性?为什么 Vuex 的 mutation 中不能做异步操作?
有五种,别离是 State、 Getter、Mutation 、Action、 Module1、state => 根本数据(数据源寄存地)2、getters => 从根本数据派生进去的数据3、mutations => 提交更改数据的办法,同步4、actions => 像一个装璜器,包裹mutations,使之能够异步。5、modules => 模块化Vuex1、Vuex中所有的状态更新的惟一路径都是mutation,异步操作通过 Action 来提交 mutation实现,这样能够不便地跟踪每一个状态的变动,从而可能实现一些工具帮忙更好地理解咱们的利用。2、每个mutation执行实现后都会对应到一个新的状态变更,这样devtools就能够打个快照存下来,而后就能够实现 time-travel 了。如果mutation反对异步操作,就没有方法晓得状态是何时更新的,无奈很好的进行状态的追踪,给调试带来艰难。复制代码