前端面试知识查漏补缺
1.AJAX
2.typeof和instance
3.addEventListenr
4.vue 的beforecreate 和created区别
5.路由懒加载有哪些方式
6.diff算法实现方式
7.webpack loader和plungin,处理image用的那个loader,限制其大小是
8.webpack如何优化打包速度
9.webpack中chunkHash 与 contentHash 区别
10.generator 有什么应用场景
11.实现一下模板字符串
12.flex的各个属性值
13.es6的proxy如何使用以及使用场所,说说reflect
14.说说http缓存,http状态吗
15.http2与http1.1区别,了解http3吗
16.说说http缓存,http状态吗
1.AJAX
用来实现异步刷新内容,在与服务器进行交换数据时候可以不重新加载整个页面实现数据的更新
1.XMLHttpRequest对象
用于在后台与服务器进行交换数据
2.open(method, url,async)
初始化,规定请求方式,请求路径以及是否处理异步请求
3.send()发送到服务器
4.readyState() 保存XMLHttpRequest状态,从0到4发生变化
- 0:请求未初始化
- 1:服务器连接已建立
- 2:请求已接收
- 3:请求处理中
- 4.请求已完成,且已准备就绪
5.onreadystatechange()事件
每当readyState属性改变时就会调用该函数
6.status
200:‘ok’
404:未找到页面
let xhr = new XMLHttpRequest //创建对象
xhr.open('get',url,true) //初始化
xhr.send() //发送请求
xhr.onreadystatechange=()=>{
if(xhr.readyState===4){
if(xhr.status>=200 && xhr.status<300){
console.log(JSON.parse(xhr.responseText))
}
}
}
2.typeof和instance
这两个都是用来判断数据类型的,但是因为原理不同,所以能判断的类型也有区别。
typeof返回的类型有六种: ‘number’ , ‘string’ , ‘boolean’ , ‘object’ 以及 ‘function’ 和 ‘undefined’.
instance of 运算符用于检验构造函数的 prototype 属性是否出现在某个实例对象的原型链上
顺着原型链去找,直到找到相同的原型对象,返回true,否则为false。返回的是布尔值
区别:
typeof 会返回一个变量的基础数据类型,而 instanceof 返回一个布尔值 instanceof
可以精准地判断复杂引用数据类型,但不能正确判断基础数据类型
typeof 虽然可以判断基础数据类型( null除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断
如果需要通用检测数据类型,可以采用 Object.prototype.toString.call(),调用该方法,统一返回格式 “[object Xxx]” 的字符串
可以自己封装一下
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null) // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined) // "undefined" typeof 直接返回
getType() // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g) //"RegExp" toString返回
3.addEventListener
使用方法
document.getElementById(元素id).addEventListener("click", function(){
console.log("目标元素被点击了");
});
三个参数
1.事件名称,字符串,必填
事件名称不用带on前缀,点击事件直接写“click”,键盘开放事件写“keyup”
2.执行函数,必填
填写需要执行的函数,如:function(){…代码}
3.布尔值,可空
true:事件在捕获阶段执行
false :事件在冒泡阶段执行,默认是false
4.vue 的beforecreate 和created区别
beforeCreate这个阶段主要是完成vue中关于生成周期以及事件的一些初始化工作.实例、组件通过 new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate 钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的 dom,一般不做操作
当执行完beforeCreate函数后,紧接着就会执行下一个环节:初始化props、data、methods,但此时页面的模板还未创建好.
当初始化props、data、methods完毕后,就会立即执行ceated(){}函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发 updated 函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
5.路由懒加载有哪些方式
为什么需要懒加载:像vue这种单页面的应用,如果没有应用的懒加载,运用webpack打包以后的文件将会异常的大,造成进入首页时,需要加载的内容过多,事件过长,会出现长时间的白屏,即使做了loading也是不利于用户体验的,而运用懒加载可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的压力,减少首页加载用时
1.vue异步组件
{ path: '/home', name: 'home', component: resolve => require(['@/components/home'],resolve) },
{ path: '/index', name: 'Index', component: resolve => require(['@/components/index'],resolve) },
{ path: '/about', name: 'about', component: resolve => require(['@/components/about'],resolve) }
2.es6的import()
const home = ()=> import('../view/home/home')
const fenlei = ()=> import('../view/fenlei/fenlei')
const gouwuche = ()=> import('../view/gouwuche/gouwuche')
const geren = ()=> import('../view/geren/geren')
3.webpack的require.ensure()
{ path: '/home', name: 'home', component: r => require.ensure([], () => r(require('@/components/home')), 'demo') },
{ path: '/index', name: 'Index', component: r => require.ensure([], () => r(require('@/components/index')), 'demo') },
{ path: '/about', name: 'about', component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01') }
6.diff算法实现方式
说起这个先说一下虚拟DOM:DOM通过js语法在内存中维护一组数据结构描述出来的模拟DOM树,当数据发生改变的时候,会先对虚拟DOM进行模拟修改,然后通过新的虚拟DOM和旧的虚拟DOM进行比较,这个对比就是通过diff算法实现的。虚拟DOM的最大意义不在于性能的提升,而是抽象了DOM的具体实现。
diff算法的实现步骤:
1,用js对象模拟DOM树
2.比较两个虚拟DOM 树的差异
3.把差异用在真正的DOM树上
在比较的的时候:
同一级比较,比较标签名,若不相同直接删除,不继续深度比较。若标签名相同,key相同,就认为是相同的节点,不继续深度比较,下面是详细介绍
1.调用patch函数比较Vnode和OldVnode,如果不一样直接return Vnode,即将Vnode真实化后替换掉DOM中的节点
2.如果OldVnode和Vnode值得进一步比较则调用patchVnode方法进行进一步比较,分为以下几种情况:
Vnode有子节点,但是OldVnode没有,则将Vnode的子节点真实化后添加到真实DOM上
Vnode没有子节点,但是OldVnode上有,则将真实DOM上相应位置的节点删除掉
Vnode和OldVnode都有文本节点但是内容不一样,则将真实DOM上的文本节点替换为Vnode上的文本节点
Vnode和OldVnode上都有子节点,需要调用updateChildren函数进一步比较
3.updateChildren比较规则
提取出Vnode和OldVnode中的子节点分别为vCh和OldCh,并且提出各自的起始和结尾变量标记为 oldS oldE newS newE
如果是oldS和newE匹配上了,那么真实dom中的第一个节点会移到最后
如果是oldE和newS匹配上了,那么真实dom中的最后一个节点会移到最前,匹配上的两个指针向中间移动
如果都没有,在没有key的情况下直接在DOM的oldS位置的前面添加newS,同时newS+1。在有key的情况下会将newS和Oldch上的所有节点对比,如果有相同的则移动DOM并且将旧节点中这个位置置为null且newS+1。如果还没有则直接在DOM的oldS位置的前面添加newS且newS+1
直到出现任意一方的start>end,则有一方遍历结束,整个比较也结束
7.webpack loader和plungin,处理image用的那个loader,限制其大小是
webpack loader是加载器,用来处理除了js和json的文件资源,plugins是插件,用来扩展webpack功能。正常情况下是先用loader编译资源再调用插件,他俩的区别首先是用的地方: plugins是在整个周期都起作用,而loader则是运行在编译的过程。使用上loader是先下载后使用,plugins是先下载,再引用最后使用。
处理image使用的loader是img-loader,一般限制其大小为10kb,在parser里面配置。小于这个会转为base64,虽然文件会变大,但是会减少请求次数
8.webpack如何优化打包速度
从两个方面来说,第一个是减少需要打包的文件或代码;另一方面就是多进程构建
1.减少需要构建的代码或文件:
- HMR热模块替换只重新构建发生变化的模块
- 缩小处理范围:合理利用两个属性:include、exclude(不需要处理的文件)
- babel缓存。第二次构建时,读取之前的缓存,只重新构建发生变化的文件
- 使用DII进行分包:分包方便按需加载,node_module正常情况下会被打包成一个文件,使用DII技术,对不经常更新的框架和库单独进行打包,生成一个chunk
2.多进程构建
多进程打包 thread_loader,将其放在浪费时间的loader之前。但由于进程的启动和通信都有开销,当工作时间很长时,才需要多进程打包
推荐一篇文章
webpack打包速度优化