前端面试题(二)

数组降维的几种方法

使用递归降维

先声明一个空数组,再声明一个函数,把要降维的数组作为参数传进去,函数体内遍历要降维的数组,判断数组中的元素是否是数组,是的话就再调用这个函数把当前元素作为参数传入,不是直接添加到声明的空数组中

将多维数组转化为字符串,再转换成一维数组

使用数组方法flat()

使用Infinity作为深度,展开任意深度的嵌套数组)

使用concat方法

利用扩展运算符

对象深度克隆

    const newObj = {};
    const clone = (newObj, oldObj) => {
      for (k in oldObj) {
        if (oldObj[k] instanceof Array) {
          newObj[k] = [];
          clone(newObj[k], oldObj[k]);
        } else if (oldObj[k] instanceof Object) {
          newObj[k] = {};
          clone(newObj[k], oldObj[k]);
        } else {
          newObj[k] = oldObj[k];
        }
      }
    }
    clone(newObj,oldObj)

数组去重

1.循环 + indexOf方法 / findIndex方法

indexOf方法:返回数组中第一次出现给定元素的下标,没有则返回-1,用法 数组.indexOf('给定元素')

findIndex方法:返回数组中第一个符合条件的元素的下标,没有则返回-1

let arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
    let newArr = []
    arr.forEach(c =>{
      newArr.indexOf(c) === -1? newArr.push(c):newArr
    })

	arr.forEach(c =>{
      newArr.findIndex(c1 =>  c === c1) === -1? newArr.push(c):newArr
    })

    console.log(newArr)  //[1,2,3,4,5,6,8]
2.利用sort()方法
    const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
    arr.sort()
    arr.forEach((c,i) =>{
      arr[i] === arr[i - 1] ? arr.splice(i,1) :arr
    })
    console.log(arr) //[1,2,3,4,5,6,8]
3.Set()构造函数

Set():Set构造函数可以创建Set对象,可以存储任意类型的唯一值(基础类型和引用类型都可以)

const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
const newArr = [...new Set(arr)]
console.log(newArr) //[1,2,3,4,5,6,8]

new Set()方法返回的是一个类数组,也可以结合Array.form() 转成真实数组

const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
const newArr = Array.from(new Set(arr))
console.log(newArr) //[1,2,3,4,5,6,8]
4.利用inclueds方法
    const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
    const newArr = []
    arr.forEach(c =>{
      newArr.includes(c)? newArr : newArr.push(c)
    })
    console.log(newArr)  //[1,2,3,4,5,6,8]

常见的http状态码及代表的含义

//1.信息代码:1xx:信息,请求收到,继续处理;
//2.成功代码:2xx:成功,行为被成功地接受、理解和采纳;
//3.重定向:3xx:重定向,为了完成请求,必须进一步执行的动作;
//4.客户端错误:4xx:客户端错误,请求包含语法错误或者请求无法实现;
//5.服务器错误:5xx:服务器错误,服务器不能实现一种明显无效的请求;

//200(ok):请求成功,请求所希望的响应头或数据体将随此响应返回
//304:指示资源未发生改变,客户端可以使用缓存版本
//400(Bad Request):请求格式错误(请求携带的参数不正确)
//401:未认证,没有登录;token过期
//403:没有访问权限
//404(Not Found):请求失败,服务器无法正常提供信息,或是服务器无法回应,且不知道原因返回的页面
//500(Internal Server Error):基本是服务器出现错误会返回的状态
//502:网关错误
//503:请求超时或停机维护

localStorage、sessionStorage、cookie的区别

共同点:都是保存在浏览器且同源的

区别:

​    1.cookie数据会在同源的http请求中携带;sessionStorage和localStorage不会自动把数据发送给服务器,仅保存在本地

​    2.cookie数据的存储大小不超过4k,sessionStorage和localStorage的存储数据是5M

​    3.sessionStorage仅在当前浏览器窗口关闭之前有效,localStorage是始终有效,cookie是在设置的过期时间内有效

​    4.sessionStorage在不同的浏览器窗口数据不能共享,即使是同一个页面;localStorage和cookie在所有的同源窗口都是共享的

一个页面从输入URL到页面 加载显示完成,这个过程中都发 生了什么

1.URL解析:地址栏输入地址,浏览器对输入的内容进行解析,判断URL的合法性、是否有可用的缓存

2.DNS解析:浏览器查找对应的IP地址

3.建立TCP连接(三次握手):浏览器向服务器发起TCP连接,与浏览器建立TCP三次握手

4.HTTP请求:浏览器将http请求数据发送给服务器(客户端->服务器)

5.HTTP响应:服务器处理接收到的请求,返回响应结果给浏览器(服务器->浏览器)

6.关闭TCP连接(四次挥手):数据传输完成后,经过四次握手终止连接

7.页面渲染:浏览器解析响应的结果,进行页面渲染

HTTP缓存机制

本地缓存基于本地环境的内存,访问速度快,对于一些变更率低、实时性要求低的数据可以放在本地缓存中,提升访问速度;使用本地缓存能够减少和redis类的远程缓存间的数据交互,减少网络I/O开销,降低这一过程中在网络通信上的耗时

为什么要使用http缓存:优化性能,提升访问速度,减少请求次数

强缓存:不向服务器发起请求,浏览器要获取特定的数据时,会先检查本地的缓存是否存在该数据,如果存在就直接在本地获取,如果不存在就向服务器索要数据

协商缓存:浏览器第一次请求数据时,服务器将缓存标识与数据一起返回给客户端,客户端将二者备份到缓存数据库中,再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后返回304状态码通知客户端比较成功可以使用缓存数据

es5和es6的区别,es6的新增内容

es6相对于es5更加简洁,提高了开发效率,新增了一些新特性

es6新增:
    1.let和const:let声明变量,const声明常量,let和const不存在变量提升,let和const声明有块级作用域,只能在块级作用域内访问

    2.symbol:一种新的基本数据类型,表示一个独一无二的值,不能与其他数据类型进行运算
    
    3.模板字符串:(`xxx${变量}`)   字符串的新方法:includes
    
    4.对象/数组解构:const {a,b} = {a:1,b:2}   const [a,b,c] = [1,2,3]
                 console.log(a,b) // 1,2     console.log(a,b,c)  // 1,2,3

    5.Set() 构造函数:Set对象是值的集合,允许存储任何类型的唯一值
    
    6.数组的新方法:
        Array.from:将伪数组转换成真数组
        includes:判断数组中是否包含一个指定的值
        map:通常用来遍历迭代加工数组
        forEach:通常用来遍历数组
        filter:筛选出数组中符合条件的所有元素返回到一个新的数组中
        find:返回数组中符合条件的第一个元素
        some:数组中有一项元素符合判断条件就返回true,只有所有元素都不符合条件才返回false
        every:数组中所有元素都符合判断条件才返回true,只要有一个不符合就返回false
    7.Object对象的新方法
        object.is():判断两个值是否指向同一内存地址
        object.assign():用于将所有可枚举属性的值从一个或多个源对象分配到目标对象
        object.keys():
        object.values():
        object.entries():
    8.对象声明简写
        let person={
              name,
              age
          }
    9.  ...拓展运算符(对象拓展符)
    10.箭头函数
    11.模块化
    12.promise

let、const、var的区别

1.var声明变量存在变量提升,let和const不存在变量提升
2.let和const声明有块级作用域,只能在块级作用域中访问
3.同一作用域下let和const不能声明同名变量,var可以
4.const定义常量不能修改,但定义的是对象时,对象的属性值可以改变

vue数据双向绑定的原理

vue数据的双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的

通过object.defineProperty()方法设置set和get函数来实现数据的劫持,在数据变化时触发相应的监听回调,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化数据也随之发生改变

Object.defineProperty 和 Proxy 的区别

object.defineProperty(obj,prop,descriptor)方法 有三个参数:
    obj:要定义属性的对象
    prop:要定义或修改的属性
    descriptor:具体的改变方法
用这个方法来定义一个值,调用时我们是使用了它里面的get方法;当给这个属性赋值时是调用了它里面的set()方法

proxy对象用于定义基本操作的自定义行为。
        const p = new Proxy(target, handler)
    target: 要使用 Proxy 包装的目标对象
    handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为

父子组件传值(父子通信)

父传子:

在父组件的子组件标签上绑定属性,将数据传递给子组件;子组件中通过props接收数据使用

子传父:

子组件中定义事件,通过$emit发送给父组件,父组件在子组件标签上通过(@自定义事件名)接收事件

this.$emit('自定义事件名',参数1,参数2,...)

vue实现组件缓存

<keep-alive>包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染

activated钩子函数:

在组件第一次渲染时会被调用,之后在每次组件被激活时调用

deactivatde钩子函数:

组件被停用时(离开路由)被调用

v-show和v-if

相同点:都能控制元素的显示与隐藏
    不同点:
            1.v-show是给绑定的DOM元素添加CSS样式display:none控制显隐,DOM元素仍然存在;    v-if是将DOM元素直接删除,DOM                 元素不再存在。

            2.v-if是惰性的,在初始判断条件为false时,初次不会渲染,v-show不管初始条件是什么都会渲染;v-if在显隐切换过程中              合适地销毁和重建内部的事件监听和子组件

            3.v-if由false变为true时,会触发组件的beforeCreate、created、beforeMount、mounted钩子,由true变为false时会                 触发组件的                beforeDestory、destoryed钩子;v-show的显隐不会触发组件的生命周期钩子

            4.v-show 的初始渲染消耗高, v-if 的切换消耗更高。

v-if和v-show的使用场景

需要非常频繁的切换时,使用v-show

在运行时条件很少改变,则使用v-if较好。

为什么避免v-if和v-for一起使用

因为v-for的优先级时高于v-if的,如果作用在同一元素上,输出的渲染函数中可以看出会先执行循环再判断条件,每次重渲染的时候遍 历整个列表,会造成性能的浪费。

v-for比v-if优先,即每一次都需要遍历整个数组,影响速度;

更好的解决方案: 是用computed先获取符合条件的数据,再进行遍历

watch、computed和methods的区别

watch用于监听指定数据的变化并执行响应操作
computed用于定义计算属性,它会根据依赖的数据自动更新计算结果
methods用于定义方法,在需要时手动调用执行

在数据变化时执行异步或开销较大的操作,可以使用watch
需要依赖其他响应式数据进行计算,且希望有缓存机制,可以使用computed
需要在模板中触发事件或执行逻辑操作,可以使用methods

vue中key值的作用

用来给每一个节点做唯一标识的属性,它的作用是帮助vue进行DOM元素的复用;当vue更新DOM时,它会基于新数据生成虚拟DOM 树,将其与旧的DOM树进行对比,通过对比找到需要更新的节点,达到更新视图的目的,在进行对比时,vue会根据key值来判断新旧 节点是否相同来决定是否进行复用。

当状态数据发生变化时,vue会根据【新数据】生成【新的虚拟dom】
随后vue进行【新的虚拟dom】与【旧的虚拟dom】的diff比较 比较规则如下:
a. 如果旧虚拟dom找到了与新虚拟dom相同的key
(1)若旧虚拟dom中内容没变,直接使用之前的真实dom
(2)若旧虚拟dom中内容发生了改变,则生成新的真实dom 随后替换掉页面中的真实dom
b. 如果旧虚拟dom未找到与新虚拟dom相同的key 
根据数据创建新的真实dom随后渲染到页面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值