2020-07面试准备

vue

1.static和assets的区别

assets和static两个都是用于存放静态资源文件。
放在static中的文件不会进行构建编译处理,也就不会压缩体积,在打包时效率会更高,但体积更大在服务器中就会占据更大的空间。
放在assets中的文件会进行压缩体积、代码格式化,压缩后会放置在static中一同上传服务器。
因此建议样式文件放在assets中进行打包,引入的第三方文件放到static中,因为引入的文件已经做过打包处理。

 2.vuex

// index.js
import Vue from "vue";
import Vuex from "vuex";
import { ADDCOUNT } from "./mutation-types"

Vue.use(Vuex);

export default new Vuex.Store({
  state: { // data(变量)
    count: 0,
    books: [{
      id: 1,
      name: '钢铁是怎样炼成的',
      price: 15
    },
    {
      id: 2,
      name: '老人与海',
      price: 6
    },
    {
      id: 3,
      name: '简爱',
      price: 12
    },
    {
      id: 4,
      name: '巴黎圣母院',
      price: 24
    }]
  },
  mutations: { // 同步methods(方法)
    [ADDCOUNT](state, count) {
      state.count += count
    },
    subCount(state) {
      state.count--
    },
    addAttr(state) {
      Vue.set(state.books[0], 'lunguage', '中文')
    },
    deleteAttr(state) {
      Vue.delete(state.books[0], 'lunguage')
    },
    upData(state, count) {
      state.count += count
    }
  },
  getters: { // computed(计算属性)
    books1(state) {
      return state.books[1]
    },
    oldPeple(state, getters) {
      return `《${state.books[1].name}》售价${getters.books1.price}元`
    },
    wantPrice(state) {
      return function (price) {
        let want = state.books.filter(v => v.price === price)
        return `《${want[0].name}》售价${want[0].price}元`
      }
    }
  },
  actions: { // 异步methods(方法)
    // context 执行上下文
    upData(context, count) {
      return new Promise((resolve) => {
        setTimeout(() => {
          context.commit('upData', count)
          resolve('成功加了' + count)
        }, 3000);
      })
    }
  },
  modules: { // 可以将store分为模块化,每个模块内都有state,mutations,getter,actions属性
    a: {
      state: {
        count: 0
      },
      mutations: {
        addCountA(state, count) {
          state.count += count
        }
      },
      getters: {
        countA(state) {
          return state.count += 10
        }
      },
      actions: {
        // 一样
      }
    },
    b: {
      state: {},
      mutations: {},
      getters: {},
      actions: {}
    }
  }
});
// mutation-types.js
export const ADDCOUNT = 'addCount';
// 使用
1.使用this.$store.state.count来获取state里面的值
2.使用this.$store.commit("addCount")来调用mutations里面的方法,并且可以在commit("addCount",count)传递参数count
3.使用$store.getters.oldPeple相当于一个单例的计算属性来获取state的值
3.1.使用getters返回一个方法来接受参数 $store.getters.wantPrice(12)
5.可以在store文件夹下创建一个mutation-types的js文件,专门用来管理mutations里面的方法名
6.actions使用:通过this.$store.dispatch('upData', count)
7.modules 
  获取模块a里面的值:{{ $store.state.a.count }}--{{ $store.getters.countA }}
  触发模块a的方法:$store.commit('addCountA', 100)

3.封装一个input输入框

1.子组件
<template>
  <div>
    <input
      type="text"
      @input="$emit('input', $event.target.value)"
      :value="value"
    />
  </div>
</template>

<script>
export default {
  name: "Form",
  props: ["value"],
};
</script>
2.父组件
<template>
  <div>
    <p>{{ value }}</p>
    <Form v-model="value"/>
  </div>
</template>

<script>
import Form from "./components/Form";
export default {
  name: "Home",
  components: {
    Form,
  },
  data() {
    return {
      value: "",
    };
  },
  created() {
    console.log(this.$route.path);
  },
};
</script>
3.v-model实现原理
<input v-model="sth" /> 等同于 <input :value="sth" @input="sth = $event.target.value" />

4.bus

1.定义Bus
const Bus = new Vue();
2.挂载Bus
Vue.prototype.$bus = Bus;
3.调用
组件一email.vue
<template>
  <div class="email"><button @click="handleClick">按我</button></div>
</template>
<script>
export default {
methods: {
  handleClick () {
      this.$bus.$emit('on-click','hello')
    }
  }
}
</script>
组件二tel.vue
<template>
  <div class="tel">{{ message }}</div>
</template>
<script>
export default {
data () {
  return {
      message: ''
  }
},
mounted () {
    this.$bus.$on('on-click',mes => {
      this.message = mes
    })
  }
}
</script>

 5.vue白屏

vue项目有个缺点,首次渲染会有一段时间的白屏原因是首次渲染时需要加载一堆资源,如js、css、图片。很多优化策略,最终目的是提高这些资源的加载速度。但是如果遇上网络慢的情况,无论优化到极致还是需要一定加载时间,
这时就会出现白屏现象。首先加载是index.html页面,其是没有内容,就会出现白屏。如果<div id="app"></div>里面有内容,就不会出现白屏。所以我们可以在<div id="app"></div>里添加首屏的静态页面。
等真正的首屏加载出来后就会把<div id="app"></div>这块结构都替换掉,给人一种视觉上的误差,就不会产生白屏。

js

1.函数防抖节流

//防抖
function debounce(func, wait) {
  let timeout;
  return function () {
    if (timeout) {
      clearTimeout(timeout)
    }
    timeout = setTimeout(() => {
      func.apply(this, arguments)
    }, wait)
  }
}

//节流
function throttle(func, wait) {
  let timeout;
  return function () {
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null;
        func.apply(this, arguments)
      }, wait)
    }
  }
}

function say() {
  console.log('hi haha')
}
document.onmousemove = debounce(say, 1000)
document.onmousemove = throttle(say, 1000)

 2.闭包

没有被引用的闭包会被自动回收,但还存在全局变量中,则依然会内存泄漏。
在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,
我们就把这些变量的集合称为闭包

比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。
function getNum() { let n = 1 return function() { n++ } } getNum() // 2 getNum() // 3 getNum() // 4 getNum() // 5

 3.new操作符

function createThis(fn) {
  let obj = {}; // 创建一个新的对象
  let [constructor, ...args] = [...arguments];
  obj.__proto__ = fn.prototype; // 把obj的__proto__指向fn的prototype,实现继承
  constructor.apply(obj, args); // 改变this的指向,执行构造函数、传递参数,fn.apply(obj,) 或者 fn.call() -- constructor是fn的构造函数 args 是传递的参数
  return obj; // 返回新的对象obj
}

let App = function () {
  Object.assign(this, {
    age: 18,
    sey() {
      console.log(this.age);
    },
  });
};

let a = createThis(App, 415);
a.sey(); // 18

 4.函数柯里化

const curry = fn => {
  if (typeof fn !== "function") {
    throw Error("No function provided")
  }
  return function curriedFn(...args) {
    if (args.length < fn.length) {
      return function () {
        return curriedFn.apply(null, args.concat([].slice.call(arguments)))
      }
    }
    return fn.apply(null, args)
  }
}

function add(a, b, c) {
  console.log(a + b + c)
}
let ad = curry(add)
ad(1)(1)(1) // 复用几次取决于有多少参数

 5.拷贝

浅拷贝指拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响.。
深拷贝完全拷贝一个新对象,修改时原对象不再受到任何影响

浅拷贝:扩展运算符、Object.assign、contact、slice等
深拷贝:
1.使用JSON.parse(JSON.stringify(obj))。性能最快。其弊端也必将明显,首先无法拷贝函数、undefined、或symbol等值。其二对象要是有自身循环调用,会报错。
2.利用递归来实现每一层都重新创建对象并赋值
3.如何用jquery,可以考虑,$.extend()

5.1简单的深拷贝-递归实现

function copy(obj) {
  let result = Array.isArray(obj) ? [] : {}
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (typeof obj[key] === 'object') {
        result[key] = deepCopy(obj[key]) // 递归复制
      } else {
        result[key] = obj[key]
      }
    }
  }
  return result
}
let a = {
    name: 'lj'
  },
  b = copy(a)
b.name = 'lc'
console.log(a, b) // {name: "lj"} {name: "lc"}

 6.js运行机制

宏任务(macro-task):整体代码script、setTimeOut、setInterval
微任务(mincro-task):promise.then、promise.nextTick(node)
需要注意的是new Promise是会进入到主线程中立刻执行,而promise.then则属于微任务
function add(x, y) {
  console.log(1)
  setTimeout(function() { // timer1
    console.log(2)
  }, 1000)
}
add()
setTimeout(function() { // timer2
  console.log(3)
})
new Promise(function(resolve) {
  console.log(4)
  setTimeout(function() { // timer3
    console.log(5)
  }, 100)
  for(var i = 0; i < 100; i++) {
    i == 99 && resolve()
  }
}).then(function() {
  setTimeout(function() { // timer4
    console.log(6) 
  }, 0)
  console.log(7)
})
console.log(8)
执行结果
//1,4,8,7,3,6,5,2

 7.从输入URL到页面显示的过程

1. 发送URL,请求IP地址
2. TCP三次握手
    第一次握手:建立连接,第二次握手:服务器收到SYN报文段,第三次握手:客户端收到SYN+ACK报文段
3.服务器响应200
4.生成Render Tree
5.渲染页面

8.原型链

8.1创建对象的几种方式

//1.字面量
let obj1 = {
    name: '阿成'
}
//2.new Object
let obj2 = new Object({
    name: '阿成'
})
//3.构造函数创建
let M = function (name) {
    this.name = name
}
let obj3 = new M('阿成')
//4.Object.create
let obj4 = Object.create({
    name: '阿成'
})

8.2原型、构造函数、实例、原型链

构造函数、原型对象、实例的关系可以参照下图:

构造函数.prototype.constructor === 构造函数

构造函数.prototype === 实例对象.proto

9.页面性能优化

1.资源压缩合并,减少 HTTP 请求
2.非核心代码异步加载(异步加载的方式,异步加载的区别)
3.利用浏览器缓存(缓存的分类,缓存原理)
4.使用 CDN
5.预解析 DNS

html5

1.良好的移动性,以移动端设备为主。
2.响应式设计,以适应自动变化的屏幕尺寸。
3.支持离线缓存技术,webStorage本地缓存。
4.新增canvas,video,audio等新。标签元素。新增特殊内容元素:article ,footer ,header,nav ,section等,新增表单控件:calendar,date,time,email,url,search。
5.地理定位.....
6.新增webSocket/webWork技术。

es6

1 let 和 const
let 在块级作用域内有效,不会污染全局变量
const 一经声明不能改变。注意保证的是它指向的内存地址不能改变,如果是对象或者数组里面的属性或元素可以改变的。
存在暂时性死区,不能变量提升。
只能先声明再使用,且不能重复声明

2 字符模板
用作字符串拼接:`你好,${name}`

3 变量的解构赋值
let [a,b,c] = [1,2,3]
交换变量的值:[a,b] = [b,a]
提取 JSON 数据,获取服务器返回数据时有用:let {data, code} = res
输入模块的指定方法:
const { SourceMapConsumer, SourceNode } = require("source-map");
从函数返回多个值: 返回个数组或对象

4 扩展运算符
扩展运算符(spread)是三个点(...)。
复制数组:let arr2 = [...arr1]
合并数组:[...arr1, ...arr2, ...arr3]

5 Promise
成功调用 resolve,失败调用 reject
.then  获取结果,.catch  捕获异常。捕获异常还可通过 .then  的第二个参数
.finally 无论成功失败都一定会调用
多个并发的请求,用 Promise.all()
只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
let p = Promise.all([p1,p2,p3])
p.then(([res1, res2,res3]) => {};
复制代码Promise 示例:
new Promise(){
    if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
}.then().catch().finally()

6 async await
async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async 函数对 Generator 函数的改进:
内置执行器,直接调用即可。Generator 还需要调用 next()才能执行
更好的语义。async  和 await  比 *  和 yield 更好理解
返回值是 Promise

7 箭头函数
箭头函数 () => {} 的 this 是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this 就继承了定义函数的对象。this 一旦确定以后不会改变。
普通函数的 this 指向的是调用它的对象。

 

原文地址:https://www.cnblogs.com/qxp140605/p/13281428.html