1、从浏览器地址栏输入url到显示页面的步骤
- 浏览器查看缓存,如果请求资源在缓存中而且未失效,则直接提供给客户端。否则将重新请求。
- 浏览器根据请求的url交给DNS域名解析,找到真实IP,向服务器发起请求。
- 服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等)
- 浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM)
- 载入解析到的资源文件,渲染页面,完成。 juejin.cn/post/684490…
2、原型
segmentfault.com/a/119000001…
www.jianshu.com/p/dee9f8b14…
www.jianshu.com/p/652991a67…
www.jianshu.com/p/a4e1e7b6f…
注意:console.log(typeof Function.prototype) // Function 这个特殊
3、W3C标准盒子模型和IE盒子模型的区别
- w3c盒子模型的范围包括margin、border、padding、content,并且content部分不包含其他部分
- IE盒子模型的范围包括margin、border、padding、content,和w3c盒子模型不同的是,IE盒子模型的content部分包含了padding和border
4、如何垂直居中一个浮动元素?
方法一: 已经知道元素高宽
// 子盒子
#div1{
width:200px;
height:200px;
position: absolute; //父元素需要相对定位
top: 50%;
left: 50%;
margin-top:-100px ; //二分之一的height,width
margin-left: -100px;
}
方法二: 未知父元素高宽
//子盒子
#div1{
width: 200px;
height: 200px;
margin:auto;
position: absolute; //父元素需要相对定位
left: 0;
top: 0;
right: 0;
bottom: 0;
background: red;
}
方法三: flex使盒子居中
// 父盒子
.da{
width: 500px;
height: 500px;
background: green;
display: flex; // 使用flex
align-items: center; // 上下居中
justify-content: center; // 左右居中
}
方法四: css3中的新属性transform实现盒子居中
.da{
/*父盒子*/
width: 500px;
height: 500px;
background: green;
position: relative;
}
#er{
/*我是子盒子我要居中*/
width: 200px;
height: 200px;
background: red;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
4、闭包
- 闭包就是能够读取其他函数内部变量的函数
- 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念
- 闭包 的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中
- 闭包的另一个用处,是封装对象的私有属性和私有方法
- 好处:能够实现封装和缓存等;
- 坏处:就是消耗内存、不正当使用会造成内存溢出的问题
使用闭包的注意点
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露
- 解决方法是,在退出函数之前,将不使用的局部变量全部删除
5、new操作符具体干了什么呢?
6、如何解决跨域问题?
跨域资源共享 CORS 详解:www.ruanyifeng.com/blog/2016/0…
7、如何通过JS判断一个数组
1、instanceof方法,instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性
Instanceof运算符的第一个变量是一个对象,暂时称为A;第二个变量一般是一个函数,暂时称为B。 Instanceof的判断队则是:沿着A的proto这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。
var arr = [];
arr instanceof Array; // true
2、constructor方法
var arr = [];
arr.constructor == Array; //true
3、Object.prototype.toString.call()
Object.prototype.toString.call(value) == '[object Array]'
// 利用这个方法,可以写一个返回数据类型的方法
var isType = function (obj) {
return Object.prototype.toString.call(obj).slice(8,-1);
}
4、ES5新增方法isArray()
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false
8、谈一谈let与var的区别
- let命令不存在变量提升,如果在let前使用,会导致报错
- 如果块区中存在let和const命令,就会形成封闭作用域
- 不允许重复声明,因此,不能在函数内部重新声明参数
9、说一下Vue的双向绑定数据的原理
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
10、快速的让一个数组乱序
var arr = [1,2,3,4,5,6,7,8,9,10];
arr.sort(function(){
return Math.random() - 0.5;
})
console.log(arr);
11、怎样添加、移除、移动、复制、创建和查找节点
创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
12、window.onload和$(document).ready
- window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。
- $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕
13、常用数组去重方法总结
方法一、利用ES6 Set去重(ES6中最常用)
function unique (arr) {
return Array.from(new Set(arr))
// return [...new Set(arr)]
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
方法二、利用for嵌套for,然后splice去重(ES5中最常用)
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
方法三、利用indexOf去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array .indexOf(arr[i]) === -1) {
array .push(arr[i])
}
}
return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重
方法四、利用includes
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array =[];
for(var i = 0; i < arr.length; i++) {
if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
array.push(arr[i]);
}
}
return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}] //{}没有去重
14、防抖/节流
15、简述ajax和axios、fetch的区别
16、Array.prototype.slice.call()方法详解
Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,除了IE下的节点集合(因为ie下的dom对象是以com对象的形式实现的,js对象与com对象不能进行转换)
多次用到 Array.prototype.slice.call(arguments, 1),不就是等于 arguments.slice(1) 吗?像前者那样写具体的好处是什么?这个很多js新手最疑惑的地方。那为什么呢?
因为arguments并不是真正的数组对象,只是与数组类似而已,所以它并没有slice这个方法,而Array.prototype.slice.call(arguments, 1)可以理解成是让arguments转换成一个数组对象,让arguments具有slice()方法。要是直接写arguments.slice(1)会报错。
17、列举一下JavaScript数组和对象有哪些原生方法?
数组:
- arr.concat(arr1, arr2, arrn);
- arr.join(",");
- arr.sort(func);
- arr.pop();
- arr.push(e1, e2, en);
- arr.shift();
- unshift(e1, e2, en);
- arr.reverse();
- arr.slice(start, end);
- arr.splice(index, count, e1, e2, en);
- arr.indexOf(el);
- arr.includes(el); // ES6 对象:
- object.hasOwnProperty(prop);
- object.propertyIsEnumerable(prop);
- object.valueOf();
- object.toString();
- object.toLocaleString();
- Class.prototype.isPropertyOf(object);
18、冒泡排序
var arr = [3, 1, 4, 6, 5, 7, 2];
function bubbleSort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for(var j = 0; j < arr.length - i - 1; j++) {
if(arr[j + 1] < arr[j]) {
var temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));
19、js中自己实现bind函数的方式
20、如何实现一个 call 函数
Function.prototype.myCall = function (context) {
if (typeof this !== 'function') {
throw new TypeError('not funciton')
}
var context = context || window
// 给 context 添加一个属性
// getValue.call(a, 'yck', '24') => a.fn = getValue
context.fn = this
// 将 context 后面的参数取出来
var args = [...arguments].slice(1)
// getValue.call(a, 'yck', '24') => a.fn('yck', '24')
var result = context.fn(...args)
// 删除 fn
delete context.fn
return result
}
21、如何实现一个 apply 函数
Function.prototype.myapply = function (context) {
if (typeof this !== 'function') {
throw new TypeError('not funciton')
}
context = context || window
context.fn = this
let result
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
22、javascript 内置类型有哪些
- 空类型:null
- 未定义:undefined
- 布尔:boolean
- 数字:number
- 字符串:string
- 对象:object
- 符号:symbol(ES6新增)
23、ES6 Proxy
es6.ruanyifeng.com/#docs/proxy
24、对于MVVM的理解
MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。
- MVVM 是 Model-View-ViewModel 的缩写
- Model: 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为
- View: 用户操作界面。当ViewModel对Model进行更新的时候,会通过数据绑定更新到View
- ViewModel: 业务逻辑层,View需要什么数据,ViewModel要提供这个数据;View有某些操作,ViewModel就要响应这些操作,所以可以说它是Model for View.
- 总结: MVVM模式简化了界面与业务的依赖,解决了数据频繁更新。MVVM 在使用当中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。
24、请详细说下你对vue生命周期的理解
25、Vue实现数据双向绑定的原理:Object.defineProperty()
26、vue路由的钩子函数
27、keep-alive的作用是什么?
28、vue自定义指令
通过注册一个 v-focus 指令,实现了在页面加载完成之后自动让输入框获取到焦点的小功能
<template>
<div>
<input v-model="form.name" v-focus />
</div>
</template>
<script>
export default {
name: 'BaseLayout',
directives: {
focus: {
// 指令的定义
inserted: (el) => {
// 聚焦元素
el.querySelector('input').focus()
}
}
}
}
</script>
29、NextTick
30、Vue 组件 data 为什么必须是函数
对象为引用类型,当复用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。
31、Vue computed原理解析
32、Proxy 相比于 defineProperty 的优势
Object.defineProperty() 的问题主要有三个
- 不能监听数组的变化
- 必须遍历对象的每个属性
- 必须深层遍历嵌套的对象
Proxy 在 ES2015 规范中被正式加入,它有以下几个特点
- 针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。这解决了上述 Object.defineProperty() 第二个问题
- 支持数组:Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的。
除了上述两点之外,Proxy 还拥有以下优势:
- Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富
- Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。
33、v-model双向绑定原理
v-model本质上是语法糖,v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件
- text 和 textarea 元素使用 value 属性和 input 事件
- checkbox 和 radio 使用 checked 属性和 change 事件
- select 字段将 value 作为 prop 并将 change 作为事件 所以我们可以v-model进行如下改写:
<input v-model="sth" />
// 等同于
<input :value="sth" @input="sth = $event.target.value" />
34、vue.extend和vue.component
35、你是如何理解Vue的响应式系统的?
响应式系统简述:
- 任何一个 Vue Component 都有一个与之对应的 Watcher 实例。
- Vue 的 data 上的属性会被添加 getter 和 setter 属性。
- 当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被读, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)
- data 被改动时(主要是用户操作), 即被写, setter 方法会被调用, 此时 Vue 会去通知所有依赖于此 data 的组件去调用他们的 render 函数进行更新。
36、说一下vue2.x中如何监测数组变化
使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。
37、vue diff算法
38、再说一下虚拟Dom以及key属性的作用
-
由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因
-
Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象
-
VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段 key的作用是尽可能的复用 DOM 元素
-
新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的
-
需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识
39、Vue中组件生命周期调用顺序说一下
- 组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。
- 组件的销毁操作是先父后子,销毁完成的顺序是先子后父
1、加载渲染过程:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
2、子组件更新过程:
父beforeUpdate->子beforeUpdate->子updated->父updated
3、父组件更新过程:
父 beforeUpdate -> 父 updated
4、销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
40、SSR了解吗
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求
41、你都做过哪些Vue的性能优化
编码阶段
- 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
- v-if和v-for不能连用
- 如果需要使用v-for给每项元素绑定事件时使用事件代理
- SPA 页面采用keep-alive缓存组件
- 在更多的情况下,使用v-if替代v-show
- key保证唯一
- 使用路由懒加载、异步组件
- 防抖、节流
- 第三方模块按需导入
- 长列表滚动到可视区域动态加载
- 图片懒加载
SEO优化
- 预渲染
- 服务端渲染SSR
打包优化
压缩代码
- Tree Shaking/Scope Hoisting
- 使用cdn加载第三方模块
- 多线程打包happypack
- splitChunks抽离公共文件
- sourceMap优化
用户体验
- 骨架屏
- PWA 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
42、vuex
43、vue 中 ajax 请求代码应该写在组件的 methods 中还是 vuex 的 action 中
如果请求来的数据不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入 vuex 的 state 里如果被其他地方复用,请将请求放入 action 里,方便复用,并包装成 promise 返回
44 v-on 的.stop、.prevent、.self、.once
- .stop 该修饰符将阻止事件向上冒泡。同理于调用 event.stopPropagation() 方法
- .prevent 该修饰符会阻止当前事件的默认行为。同理于调用 event.preventDefault() 方法
- .self 该指令只当事件是从事件绑定的元素本身触发时才触发回调
- .once 该修饰符表示绑定的事件只会被触发一次
45、实现一个简洁版的promise
es6.ruanyifeng.com/#docs/promi…
// 三个常量用于表示状态
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function MyPromise(fn) {
const that = this
this.state = PENDING
// value 变量用于保存 resolve 或者 reject 中传入的值
this.value = null
// 用于保存 then 中的回调,因为当执行完 Promise 时状态可能还是等待中,这时候应该把 then 中的回调保存起来用于状态改变时使用
that.resolvedCallbacks = []
that.rejectedCallbacks = []
function resolve(value) {
// 首先两个函数都得判断当前状态是否为等待中
if(that.state === PENDING) {
that.state = RESOLVED
that.value = value
// 遍历回调数组并执行
that.resolvedCallbacks.map(cb=>cb(that.value))
}
}
function reject(value) {
if(that.state === PENDING) {
that.state = REJECTED
that.value = value
that.rejectedCallbacks.map(cb=>cb(that.value))
}
}
// 完成以上两个函数以后,我们就该实现如何执行 Promise 中传入的函数了
try {
fn(resolve,reject)
}cach(e){
reject(e)
}
}
// 最后我们来实现较为复杂的 then 函数
MyPromise.prototype.then = function(onFulfilled,onRejected){
const that = this
// 判断两个参数是否为函数类型,因为这两个参数是可选参数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v=>v
onRejected = typeof onRejected === 'function' ? onRejected : e=>throw e
// 当状态不是等待态时,就去执行相对应的函数。如果状态是等待态的话,就往回调函数中 push 函数
if(this.state === PENDING) {
this.resolvedCallbacks.push(onFulfilled)
this.rejectedCallbacks.push(onRejected)
}
if(this.state === RESOLVED) {
onFulfilled(that.value)
}
if(this.state === REJECTED) {
onRejected(that.value)
}
}
46、设计模式
blog.poetries.top/FE-Intervie… 设计模式部分
47、手写 XMLHttpRequest
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
// 这里的函数异步执行,可参考之前 JS 基础中的异步模块
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert(xhr.responseText)
}
}
}
xhr.open("GET", "/api", false)
xhr.send(null)
48、清除浮动的方法
49、CSS3 动画
div {
width: 100px;
height: 50px;
position: absolute;
animation-name: testAnimation;
animation-duration: 5s;
}
@keyframes testAnimation
{
0% {background: red; left:0; top:0;}
25% {background: yellow; left:200px; top:0;}
50% {background: blue; left:200px; top:200px;}
75% {background: green; left:0; top:200px;}
100% {background: red; left:0; top:0;}
}
50、何为构建工具
“构建”也可理解为“编译”,就是将开发环境的代码转换成运行环境代码的过程。开发环境的代码是为了更好地阅读,而运行环境的代码是为了更快地执行,两者目的不一样,因此代码形式也不一样。例如,开发环境写的 JS 代码,要通过混淆压缩之后才能放在线上运行,因为这样代码体积更小,而且对代码执行不会有任何影响。总结一下需要构建工具处理的几种情况:
- 处理模块化:CSS 和 JS 的模块化语法,目前都无法被浏览器兼容。因此,开发环境可以使用既定的模块化语法,但是需要构建工具将模块化语法编译为浏览器可识别形式。例如,使用 webpack、Rollup 等处理 JS 模块化。
- 编译语法:编写 CSS 时使用 Less、Sass,编写 JS 时使用 ES6、TypeScript 等。这些标准目前也都无法被浏览器兼容,因此需要构建工具编译,例如使用 Babel 编译 ES6 语法。
- 代码压缩:将 CSS、JS 代码混淆压缩,为了让代码体积更小,加载更快。
51、实现深拷贝
function deepCopy(obj){
//判断是否是简单数据类型,
if(typeof obj == "object"){
//复杂数据类型
var result = obj.constructor == Array ? [] : {};
for(let i in obj){
result[i] = typeof obj[i] == "object" ? deepCopy(obj[i]) : obj[i];
}
}else {
//简单数据类型 直接 == 赋值
var result = obj;
}
return result;
}
52、模拟Object.create
// 模拟 Object.create
function create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
53、查找字符串中出现最多的字符和个数
let str = "abcabcabcbbccccc"
let arr = str.split('')
let obj = {}
arr.forEach(item => {
if (Reflect.has(obj, item)) {
obj[item]++
} else {
obj[item] = 1
}
})
console.log(obj) // {a: 3, b: 5, c: 8}
54、Vue.js 运行机制全局概览
blog.poetries.top/FE-Intervie…
55、flex布局
56、在v-model上怎么用Vuex中state的值?
需要通过computed计算属性来转换。
<input v-model="message">
// ...
computed: {
message: {
get () {
return this.$store.state.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
57、vue总结
58、cookie和session token知识
token知识:www.cnblogs.com/xuxinstyle/…
cookie和session的区别和联系:www.pianshen.com/article/157…
59、BFC 块级格式化上下文
60、display:inline-block元素之间空隙的产生原因和解决办法
61、继承
62、Object.create()方法 常用于继承使用
Object.create()接收两个参数:
- 第一个参数是作为新对象的原型的对象
- 第二个参数是定义为新对象增加额外属性的对象(这个是可选属性)
- 如果没有传递第二个参数的话,就相当于直接运行object()方法
比如说我们现在要创建一个新对象B,那么要先传入第一个参数对象A,这个A将被作为B prototype;
var A = {
name:'A',
color:['red','green']
}
//使用Object.create方法先复制一个对象
var B = Object.create(A);
这时候我们console.log(B)
可以看到结果
所以它是可以直接把A对象作为了B的原型对象的
这是我们再看看第二个参数的用法
var A = {
name:'A',
color:['red','green']
}
//使用Object.create方法先复制一个对象
var B = Object.create(A, {
age: {
value: 24
}
});
这时候console.log(B)
63、Object.assign()用法
64、es6中class类
65、怎样添加、移除、移动、复制、创建和查找节点
66、正则表达式
67、vue-router知识
68、vue-router的3种钩子函数(全局钩子、单个路由钩子、组件内钩子)
69、vuex Module模块化管理
70、作用域链和原型链
71、计算属性computed和侦听器watch
72、说说异步
73、Vue 中 $nextTick 机制和异步async await的机制
74、webpack的mode设置为prodction后做了什么?
-
tree shaking tree shaking 是一个术语,通常用于打包时移除 JavaScript 中的未引用的代码(dead-code),它依赖于 ES6 模块系统中 import和 export的静态结构特性。 开发时引入一个模块后,如果只使用其中一个功能,上线打包时只会把用到的功能打包进bundle,其他没用到的功能都不会打包进来,可以实现最基础的优化
-
scope hoisting scope hoisting的作用是将模块之间的关系进行结果推测, 可以让 Webpack 打包出来的代码文件更小、运行的更快 scope hoisting 的实现原理其实很简单:分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并。 由于 scope hoisting 需要分析出模块之间的依赖关系,因此源码必须采用 ES6 模块化语句,不然它将无法生效。
原因和tree shaking一样。
let a = 1
let b = 2
let c = 3
console.log(a + b + c)
如上面的代码 打包完后代码后只会显示console.log(6) 而定义a b c的代码将会被清除掉,因为prodction模式会提前推测出结果
- 代码压缩
所有代码使用UglifyJsPlugin插件进行压缩、混淆
75、Vue 内部是怎么知道 computed 依赖的?
76、Vue中mixins的使用方法
vue局部混入和全局混入Vue.mixin:www.cnblogs.com/bai-xue/p/1…
77、Vue.extend使用
78、VUE修饰符sync
79、Reflect的使用
es6.ruanyifeng.com/#docs/refle…
80、IP 协议、TCP 协议和 DNS 服务在使用 HTTP 协议的通信过程中各自发挥了哪些作用
81、代理、网关、隧 道
代理:
代理是一种有转发功能的应用程序,它扮演了位于服务器和客户 端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时 也接收服务器返回的响应并转发给客户端。
网关:
网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请 求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客 户端可能都不会察觉,自己的通信目标是一个网关。
隧道:
隧道是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方 通信连接的应用程序。
82、实用webpack插件之ProvidePlugin
83、使用require.context实现前端工程自动化
84、vue.config.js配置文档
85、深拷贝的使用场景,实现方式有哪些
其作用是为了不影响拷贝后的数组对起原数组造成影响。这时我们就需要进行深拷贝
1、JSON.stringify()以及JSON.parse()
2、 递归拷贝