2020-05-14 面经1

① for...in for...of(es6引入)

  • for...in 循环遍历key
  • for...of 循环遍历item,对象默认无法使用,因为没有部署Iterator遍历器接口。如果和Object.keys()搭配使用,即使不部署iterator接口也可以遍历。

② async await理解

  • 引入promise,是异步编程的一种方式,解决了ES6之前的回调地狱的问题。
  • async 返回的是一个promise对象。
  • async 函数中可以不包含await , 但是await 必须在 async函数中,await后面的表达式可以是promise,也可以是非promise,如果是promise,则返回值就是promiseresolve()的值,如果promiserejecte(),那么需要使用try catch来捕获异常,如果是非promise值,返回值就是表达式的返回值。
  • asyncawait 算是promise的语法糖,真正实现了没有回调函数获取到值。ps : then()也算是回调函数。

③ v-model 双向绑定原理

  • 本质上是 v-bindv-on的结合体
  • 通过订阅发布结合 Object.defineProperty()实现双向绑定。
    • Object.defineProperty()劫持了属性的getset方法,一旦数据发生改变,则会通知订阅者发布更新(update),从而更新视图。

④ vue的通信方式

④ - ① 组件间通信的方式

  • 父子组件通信
    1. props(父 -> 子) $emit(子 -> 父)
    2. $parent $children , 访问父组件实例,或子组件实例
    3. provide/ inject, 是vue2.2.0新增的api,父组件中配置了provide,子组件配置inject注入即可。(示例代码如下:C 是 B 的子组件,B 是 A 的子组件)
// A.vue

<template>
  <div>
    <comB></comB>
  </div>
</template>

<script>
  import comB from '../components/test/comB.vue'
  export default {
    name: "A",
    provide: {
      for: "demo"
    },
    components:{
      comB
    }
  }
</script>
// B.vue

<template>
  <div>
    {{demo}}
    <comC></comC>
  </div>
</template>

<script>
  import comC from '../components/test/comC.vue'
  export default {
    name: "B",
    inject: ['for'],
    data() {
      return {
        demo: this.for
      }
    },
    components: {
      comC
    }
  }
</script>
// C.vue
<template>
  <div>
    {{demo}}
  </div>
</template>

<script>
  export default {
    name: "C",
    inject: ['for'],
    data() {
      return {
        demo: this.for
      }
    }
  }
</script>
  • ref refs
    • 如果在普通的DOM元素上使用,则引用是DOM元素,如果是子组件使用,引用则是子组件的实例,可以通过实例直接调用组件方法或者访问组件数据。
  • EventBus 不推荐使用,当项目过大时,难以维护
  • VueX
  • localStorage / sessionStorage

④ - ② 路由间传参

⑤ vue计算属性缓存原理?

⑥ 深拷贝浅拷贝

  • 深浅拷贝一般发生在引用类型上面,普通数据类型永远都是深拷贝。当拷贝引用类型时,拷贝的仅仅是引用,内存中的地址值还是相同的。即改变拷贝后的数据,会对原数据发生影响。
  • 修改副本数据影响原数据的是浅拷贝,不影响源数据的是深拷贝。
  • 深拷贝的实现:
    1. lodash函数库
    2. 递归实现、
    3. JSON.parse(JSON.stringify())、如果对象中有function,undefined,regExp则会忽略
    4. concatslice也可以实现(仅对基本类型的数据生效)

⑦ 介绍一下http,https,为什么https比http更安全?

  • http:超文本传输协议,以明文的形式传输内容,不提供任何加密。攻击者一旦获取到传输报文,就可以读取到报文信息
  • https:安全套接字层超文本传输协议,在http的基础上添加了SSL协议,SSL依靠证书来验证服务器的身份,并未浏览器和服务器之间的通信加密。
https的原理
  1. 发送HTTPS请求,连接到server的433端口
  2. 在服务端配置数字证书
  3. 传送证书
  4. 客户端解析并验证证书的有效性
  5. 加密信息(用的是证书加密后的随机值,客户端和服务端的通信就可以进行加密了)
  6. 服务端解析加密信息
  7. 传输加密信息
  8. 客户端接收信息
https的优缺点
  • 优点:安全,SEO(搜索排名靠前)
  • 缺点:费用,SEO(页面加载变慢,功耗增大,并非绝对安全)

⑧ forEach 和 map 的区别

  • forEch没返回值,或者说返回值是undefined,直接在函数内操作循环项目。会改变原数组。
  • map 返回一个操作后的数组,不会改变原数组。一般在函数内return

⑨ 垂直居中方式

  • 定位
  • flex布局
  • grid布局
  • vertical-align:middel (图片垂直居中)
  • line-height: (文字图片垂直居中)

⑩ Tcp三次握手,四次挥手原理

⑪ 输出url到页面完成的整个过程?

  1. 查找缓存,看是否有缓存好的资源可以提高加载速度。
  2. DNS解析,将域名解析成IP地址。
  3. TCP三次握手(双方发包的过程)
  4. 发送HTTP请求
  5. 服务端处理HTTP请求,并返回响应报文
  6. 浏览器接受响应报文并解析,并且渲染
  7. 断开连接(TCP四次挥手)
关于第六步:

如果返回的是HTML页面,浏览器会将html解析成dom树,css解析成css规则树,结合dom树和规则树形成渲染树。根据渲染树中的每一个DOM节点计算出相应的位置后开始渲染。

⑫ 排序算法,冒泡排序?

  • Array.prototype.sort(),使用的是快速排序。
冒泡排序(思路如下)
  • 数组中有n个数,比较相邻的的两个数,如果前者大于后者,就把两个数字交换位置。这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过(n-1)轮,就完成了所有数的排序。
冒泡排序
// 冒泡排序写法
const arr = [1, 20, 10, 30, 22, 11, 55, 24, 31, 88, 12, 100, 50];

function swap(arr, i, j){
  const temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

for(let i = 0; i < arr.length - 1; i++){
  let flag = false;
  for(let j = 0; j < arr.length - 1 - i; j++){
    if(arr[j] > arr[j+1]){
      swap(arr, j, j+1);
      flag = true;
    }
  }

  if(!flag){
    break;
  }
}

⑬ web安全性?

  • xss攻击 :两大要素:攻击者提交恶意代码,浏览器执行恶意代码。解决方案:防止用户注入恶意代码。
  • csrf攻击 : 使用cookie冒充用户发送请求,导致目标网站错误响应
  • dns劫持 : dns涉嫌违法,较少
  • http劫持 : 使用https

⑭ 变量提升?

  • var会变量提升
  • function 声明也会函数提升

⑮ Node.js理解?文件读写?

  • 理解 : 既是开发平台,也是运行环境。基于v8引擎开发的,所以编程时使用javascript,可以理解为 让js在服务器上运行的平台。
  • 文件读写: 引入require('fs')模块,fs.writeFile() 、 fs.readFile()

⑯ 手写Map方法

  • 第一个参数是函数,第二个参数可指定函数中的this
Array.prototype._map = function(fn,thisValue){
  // 赋值数组给arr
  let arr = thisValue || this
  // 声明一个空数组,作为将要返回的结果
  let result = []
  // 判断第一个参数是否为函数
  if(typeof fn !== 'function'){
    throw new Error(fn + '该参数必须要为函数')
  }
  // 进行循环并且将执行结果返回
  for (let i = 0; i < arr.length ; i ++){
    let r = fn.call(arr , arr[i] , i , arr)
    result.push(r)
  }
  return result
}
let myMapVal = [1,2,8,6]._map((item)=>{
  return item * 2
})
console.log(myMapVal)  //  [2, 4, 16, 12]

⑰ 箭头函数与普通函数的区别?

  • 箭头函数写法更为简洁
  • 箭头函数内部没有this,箭头函数中的this执行编写时的环境。
  • call、apply、bind无法改变 this的指向
  • 箭头函数继承而来的this,指向永远不会改变
  • 构造函数不能使用箭头函数
  • 箭头函数没有自己的arguments
  • 箭头函数没有原型 prototype
  • 箭头函数不能用作Generator函数,不能使用yeild关键字

⑱ 何时用Object,何时用Map

  • 当我们只需要用到一个简单,便于操作的键值对数据结构时,用Map更具有优势。因为Map具有各种操作数据的方法,get set has delete等。但是Object始终是基石,因为JSON是直接支持转换为Object的,JSON暂未支持Map结构。

⑲ 原型链理解

  • 当访问实例对象的属性或者方法时,首先会在自身查找看是否有定义,如果没有就去__proto__属性查找,一直到原型链的顶端(null),因为Object.proto为null,如果还没有则报错(属性是输出undefined,函数是 xxx is not a function)。
  • 首先说原型 、 再说原型与实例的关系。

⑳ new 关键字背后所做的事情

  1. new 执行的构造函数,函数内部默认生成了一个对象。
  2. 函数内部的this,指向新生成的对象。
  3. new 执行后生成的对象,默认是该构造函数的返回值。

㉑ 介绍一下 Set 和 Map 结构

Set
  • 类似于数组,只不过该结构内的成员是不重复的。比数组丰富的操作方法,如 add,delete,has,clear , 属性:size
  • 遍历方法(注意:set结构没有key,或者说key和value是同一个值)
    1. Set.prototype.keys() 遍历键名
    2. Set.prototype.values() 遍历键值
    3. Set.prototype.entries() 遍历键值对
    4. Set.prototype.forEach(()=>{}) 使用回调函数的方法遍历
weakSet
  • 使用 new weakSet() , 参数只能是数组,数组中成员必须是对象。
Map
  • 类似于对象,有比对象丰富的操作方法,如 add,get,set,delete,has,属性:size
  • 遍历方法
    1. Set.prototype.keys() 遍历键名
    2. Set.prototype.values() 遍历键值
    3. Set.prototype.entries() 遍历键值对
    4. Set.prototype.forEach(()=>{}) 使用回调函数的方法遍历

⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容