某大厂面试原题(下)

简介: 本文适合最近在考虑新机会的小伙伴阅读

链表和数组的区别


链表:

一种上一个元素的引用指向下一个元素的存储结构,链表通过指针来连接元素与元素。


单向链表、双向链表、循环链表


不同:

  • 链表是链式的存储结构;数组是顺序的存储结构。
  • 链表通过指针来连接元素与元素,数组则是把所有元素按次序依次存储。
  • 链表的插入删除元素相对数组较为简单,不需要移动元素,且较为容易实现长度扩充,但是寻找某个元素较为困难;
  • 数组寻找某个元素较为简单,但插入与删除比较复杂,由于最大长度需要再编程一开始时指定,故当达到最大长度时,扩充长度不如链表方便。


相同:

  • 两种结构均可实现数据的顺序存储,构造出来的模型呈线性结构。


Vue题型

Vue.use原理

vue 首先判断这个插件是否被注册过,不允许重复注册,并且接收的 plugin 参数的限制是 Function | Object 两种类型。


对于这两种类型有不同的处理。

首先将传入的参数整理成数组:const args = toArray(arguments, 1);

再将 Vue 对象添加到这个数组的起始位置 args.unshift(this) ,这里的 this 指向 Vue 对象;

如果传入的 plugin(Vue.use的第一个参数) 的 install 是一个方法。也就是说如果传入一个对象,对象中包含 install 方法,那么就调用这个 plugin 的 install 方法并将整理好的数组当成参数传入 install 方法中, plugin.install.apply(plugin, args);

如果传入的 plugin 就是一个函数,那么就直接调用这个函数并将整理好的数组当成参数传入, plugin.apply(null, args);

之后给这个插件添加至已经添加过的插件数组中,标示已经注册过 installedPlugins.push(plugin);

最后返回 Vue 对象。


源码

toArray

export function toArray (list: any, start?: number): Array<any> {
  start = start || 0
  let i = list.length - start
  const ret: Array<any> = new Array(i)
  while (i--) {
    ret[i] = list[i + start]
  }
  return ret
}


import { toArray } from '../util/index'
export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }
    // additional parameters
    const args = toArray(arguments, 1)
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
  }
}


Keep alive生命周期

作用:缓存组件内部状态,避免重新渲染

用法keep-alive可以接收3个属性做为参数进行匹配对应的组件进行缓存:

  • include包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存)
  • exclude排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存)
  • max缓存组件的最大值(类型为字符或者数字,可以控制缓存组件的个数)

生命周期

  • 初次进入时:created > mounted > activated;退出后触发 deactivated
  • 再次进入:会触发 activated;事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated


vue3 Proxy双向绑定的原理

定义:

Proxy对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。

对目标对象的操作之前提供了拦截,可以对外界的操作进行过滤和改写,修改某些操作的默认行为,这样我们可以不直接操作对象本身,而是通过操作对象的代理对象来间接来操作对象,达到预期的目的~

const toto = new Proxy(target, handler)
// target: 是指将被代理/包裹的对象
// handler: 是代理的配置,它将拦截对目标的操作(获取、设置等)

demo

const toto = {
   name: 'toto',
   age: 25,
   _secret: '***'
}
const handler = {
  get(target, prop) {
   if (prop.startsWith('_')) {
       throw new Error('Access denied')
    }
    return target[prop]
  },
  set(target, prop, value) {
   if (prop.startsWith('_')) {
       throw new Error('Access denied')
    }
    target[prop] = value
    // set方法返回布尔值
    // 以便让我们知道该值是否已被正确设置 !
    return true
  },
  ownKeys(target, prop) {
     return Object.keys(target).filter(key => !key.startsWith('_'))
  },
}
const totoProxy = new Proxy (toto, handler)
for (const key of Object.keys(proxy1)) {
  console.log(key) // 'name', 'age'
}


v-model语法糖原理

在vue2.0中v-mode语法糖简写的代码:

<Son :value="msg" @input="msg=$event" />
简写:
<Son v-model="count" />


在vue3.0中v-model语法糖有所调整:

<Son :modelValue="msg" @update:modelValue="msg=$event" />
简写:
<Son v-model="count" />


总结:

  • vue3.0封装组件支持v-model的时候,父传子:modelValue 子传父 @update:modelValue


Tips:vue2.0的 xxx.sync 语法糖解析 父传子 :xxx 子传父 @update:xxx 在vue3.0 使用 v-model:xxx 代替。


React题型


hooks使用中有什么要注意的?

1. useState--不使用函数就set依赖之前状态的的状态

// initialState
const [visible, setVisible] = useState(false)
// modify the state
// bad 
setVisible(!visible)
// good
setVisible(visible => !visible)


2. useState--它的setter方法其实是异步的

3. 有时候使用hook莫名其妙组件卡顿了,这个时候可以考虑用useMemo

4.区分好useCallbackuseMemo一个是「缓存函数」, 一个是缓存「函数的返回值」

5. 在组件内部,会成为其他useEffect依赖项的方法,建议用 useCallback 包裹,或者直接编写在引用它的useEffect中。

6. 如果function会作为props传递给子组件,一定要使用 useCallback 包裹

7. 使用高阶函数的场景,建议使用 useMemo


react更新的流程是怎样的?

React在props或state发生改变时,会调用render()方法,创建一棵不同的树。

image.png


  • 同层节点之间相互比较,不会垮节点比较
  • 不同类型的节点,产生不同的树结构
  • 通过key来指定哪些节点在不同的渲染下保持稳定



Diffing算法(调和算法):

1.对比不同类型的元素,节点不同就会拆解原来的树,建立新树

2.对比同类型元素

3.对子节点进行递归


hooks中为什么不能使用if else 逻辑判断?

确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确

在hooks/src/index.js 下,找到 useState源码,底层调用了 useReducer是通过全局索引去获取 Hook state。


hooks和类组件有什么区别?

hooks与类组件的区别,根本的原因,心智模型(mental model)上的区别。

1、函数式组件更加“声明式”

2、函数式组件更加“函数式和易复用”


使用 React Hooks 相比于从前的类组件有以下几点好处:

  • 1. 代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护

  • 2. 组件树层级变浅,在原本的代码中,我们经常使用 HOC/render/Props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,而在 React Hooks 中,这些功能都可以通过强大的自定义的 Hooks 来实现


hooks的限制

1. hook只能用在函数组件中,class组件不行2. 普通函数不能使用hook3. 函数组件内部的函数也不行4. hook定义时要注意先后顺序5. hook函数一定要放在函数组件的第一层,别放在if/for中


开放题型


做过哪些性能优化

web 性能优化?降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩, webP,lazyLoad。加快请求速度:预解析 DNS,减少域名数,并 行加载,CDN 分发。缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存 localStorage。渲染:JS/CSS 优化,加载顺序,服务端渲染,pipeline


小程序的首屏加载时间提前请求:异步数据数据请求不需要等待页面渲染完成利用缓存:利用 storage API 对异步请求数据进行缓存,二次启动时 先利用缓存数据渲染页面,再进行后台更新避免白屏:先展示页面骨架和基础内容 及时反馈:及时地对需要用户等待的交互操作给出反馈,避免用户以 为小程序没有响应性能优化:避免不当使用 setdata 和 onpagescroll

也可以回答webpack等其他自己做过的优化内容,最好回答自己有把握的内容。


最近在学的新技术

 这个因人而异,自由发挥,最好回答一些比较热门,主流的技术。


三、最后


这套题目,考到的知识点比较全面,所以我们在平时学习的时候要多多去挖掘,"蜻蜓点水 "的背后是要深入。

相关文章
|
7月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
阿里6月面试原题出炉:Spring+SpringMvc+MyBatis(附答案)
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录
|
JavaScript 算法 前端开发
某中型公司面试原题(下)
本文适合最近在考虑新机会的的小伙伴阅读
某中型公司面试原题(下)
|
存储 缓存 前端开发
某中型公司面试原题(上)
本文适合最近在考虑新机会的的小伙伴阅读
某中型公司面试原题(上)
|
存储 JavaScript 前端开发
百度某部门面试原题(上)
本文适合最近在考虑新机会的的小伙伴阅读
百度某部门面试原题(上)
|
存储 Web App开发 设计模式
某大厂面试原题(上)
本文适合最近在考虑新机会的小伙伴阅读
|
存储 域名解析 缓存
百度某部门面试原题(下)
本文适合最近在考虑新机会的的小伙伴阅读
|
算法 搜索推荐
LintCode 题解丨阿里巴巴面试原题:两个排序数组的中位数
LintCode 题解丨阿里巴巴面试原题:两个排序数组的中位数
LintCode 题解丨阿里巴巴面试原题:两个排序数组的中位数
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!