面试整理

294 阅读11分钟

1、从浏览器地址栏输入url到显示页面的步骤

  • 浏览器查看缓存,如果请求资源在缓存中而且未失效,则直接提供给客户端。否则将重新请求。
  • 浏览器根据请求的url交给DNS域名解析,找到真实IP,向服务器发起请求。
  • 服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等)
  • 浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM)
  • 载入解析到的资源文件,渲染页面,完成。 juejin.cn/post/684490…

2、原型

1.png 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 ;   //二分之一的heightwidth
    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中可能导致内存泄露
  • 解决方法是,在退出函数之前,将不使用的局部变量全部删除

zhuanlan.zhihu.com/p/56490498

juejin.cn/post/684490…

5、new操作符具体干了什么呢?

www.jianshu.com/p/fc50c2a7d…

6、如何解决跨域问题?

juejin.cn/post/684490…

跨域资源共享 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、防抖/节流

segmentfault.com/a/119000001…

15、简述ajax和axios、fetch的区别

www.pianshen.com/article/589…

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函数的方式

blog.csdn.net/lovefengruo…

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路由的钩子函数

router.vuejs.org/zh/guide/ad…

27、keep-alive的作用是什么?

www.cnblogs.com/ljx20180807…

28、vue自定义指令

cn.vuejs.org/v2/guide/cu…

zhuanlan.zhihu.com/p/64362889

通过注册一个 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

www.cnblogs.com/leiting/p/1…

30、Vue 组件 data 为什么必须是函数

对象为引用类型,当复用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。

31、Vue computed原理解析

zhuanlan.zhihu.com/p/53219652

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

www.jianshu.com/p/2d2f42248…

35、你是如何理解Vue的响应式系统的?

响应式系统简述:

  • 任何一个 Vue Component 都有一个与之对应的 Watcher 实例。
  • Vue 的 data 上的属性会被添加 getter 和 setter 属性。
  • 当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被读, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)
  • data 被改动时(主要是用户操作), 即被写, setter 方法会被调用, 此时 Vue 会去通知所有依赖于此 data 的组件去调用他们的 render 函数进行更新。

juejin.cn/post/684490…

36、说一下vue2.x中如何监测数组变化

使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。

37、vue diff算法

juejin.cn/post/684490…

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总结

juejin.cn/post/685003…

58、cookie和session token知识

token知识:www.cnblogs.com/xuxinstyle/…

cookie和session的区别和联系:www.pianshen.com/article/157…

59、BFC 块级格式化上下文

blog.csdn.net/sinat_36422…

blog.csdn.net/return_js/a…

blog.csdn.net/weixin_4143…

60、display:inline-block元素之间空隙的产生原因和解决办法

blog.csdn.net/qq_32614411…

61、继承

segmentfault.com/a/119000000…

segmentfault.com/a/119000000…

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()用法

www.jianshu.com/p/d5f572dd3…

64、es6中class类

www.jianshu.com/p/86267fab4…

www.jianshu.com/p/0aa8c9c52…

www.jianshu.com/p/5585412b4…

65、怎样添加、移除、移动、复制、创建和查找节点

blog.csdn.net/qi127119979…

66、正则表达式

www.zhihu.com/question/48…

67、vue-router知识

www.jianshu.com/p/4c5c99abb…

68、vue-router的3种钩子函数(全局钩子、单个路由钩子、组件内钩子)

69、vuex Module模块化管理

www.jianshu.com/p/83d5677b0…

70、作用域链和原型链

www.jianshu.com/p/cc79f22b9…

71、计算属性computed和侦听器watch

cn.vuejs.org/v2/guide/co…

72、说说异步

juejin.cn/post/684490…

73、Vue 中 $nextTick 机制和异步async await的机制

juejin.cn/post/684490…

www.cnblogs.com/leiting/p/1…

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 依赖的?

www.jianshu.com/p/c9e3df578…

76、Vue中mixins的使用方法

www.cnblogs.com/Ivy-s/p/993…

vue局部混入和全局混入Vue.mixin:www.cnblogs.com/bai-xue/p/1…

77、Vue.extend使用

blog.csdn.net/lixianghai2…

www.cnblogs.com/hentai-miao…

78、VUE修饰符sync

www.jianshu.com/p/d42c508ea…

79、Reflect的使用

es6.ruanyifeng.com/#docs/refle…

80、IP 协议、TCP 协议和 DNS 服务在使用 HTTP 协议的通信过程中各自发挥了哪些作用

81、代理、网关、隧 道

代理:

代理是一种有转发功能的应用程序,它扮演了位于服务器和客户 端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时 也接收服务器返回的响应并转发给客户端。

网关:

网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请 求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客 户端可能都不会察觉,自己的通信目标是一个网关。

隧道:

隧道是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方 通信连接的应用程序。

82、实用webpack插件之ProvidePlugin

segmentfault.com/a/119000002…

83、使用require.context实现前端工程自动化

www.jianshu.com/p/c894ea00d…

84、vue.config.js配置文档

cli.vuejs.org/zh/config/#…

85、深拷贝的使用场景,实现方式有哪些

其作用是为了不影响拷贝后的数组对起原数组造成影响。这时我们就需要进行深拷贝

1、JSON.stringify()以及JSON.parse()

2、 递归拷贝