记录--为啥面试官总喜欢问computed是咋实现的?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
从computed的特性出发
computed最耀眼的几个特性是啥?
1. 依赖追踪
import { reactive, computed } from 'vue'
const state = reactive({
a: 1,
b: 2,
c: 3,
})
const sum = computed(() => {
return state.a + state.b
})
我们定义了一个响应式数据state和一个计算属性sum, Vue会自动追踪sum依赖的数据state.a和state.b,并建立相应的依赖关系。
也就是只有state.a和state.b发生变化的时候,sum才会重新计算而state.c任由它怎么变,sum都将丝毫不受影响。
2. 缓存
还是上面的例子,如果state.a和state.b打死都不再改变值了,那么我们读取sum的时候,它将会返回上一次计算的结果,而不是重新计算。
3. 懒计算
这个特性比较容易被忽略,简单地说只有计算属性真正被使用(读取)的时候才会进行计算,否则咱就仅仅是定义了一个变量而已。
import { reactive, computed } from 'vue'
const state = reactive({
a: 1,
b: 2,
c: 3
})
const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
})
setTimeout(() => {
// 没有读取sum.value之前,sum不会进行计算
console.log('1-sum', sum.value)
// 我们改变了a的值,但是sum并不会立刻进行计算
state.a = 4
setTimeout(() => {
// 而是要等到再次读取的时候才会触发重新计算
console.log('2-sum', sum.value)
}, 1000)
}, 1000)

挨个实现computed特性
1. 懒计算
我们依旧围绕effect函数来搞事情,到目前为止,effect注册的回调都是立刻执行。
const state = reactive({
a: 1,
b: 2,
c: 3
})
// 有没有很像计算属性的感觉
const sum = effect(() => {
console.log('执行计算') // 立刻被打印
const value = state.a + state.b
return value
})
console.log(sum) // undefined
想要实现computed的懒执行,咱们可以参考上篇文章Vue3:原来你是这样的“异步更新”的思路,添加一个额外的参数lazy。
它要实现的功能是:如果传递了lazy为true,副作用函数将不会立即执行,而是将执行的时机交还给用户,由用户决定啥时候执行。
当然啦!回调的结果我们也应该一并返回(例如上面的value值)
你能想象,我们仅仅需要改造几行代码就能离computed近了一大步。
const effect = function (fn, options = {}) {
const effectFn = () => {
// ... 省略
// 新增res存储fn执行的结果
const res = fn()
// ... 省略
// 新增返回结果
return res
}
// ... 省略
// 新增,只有lazy不为true时才会立即执行
if (!options.lazy) {
effectFn()
}
// 新增,返回副作用函数让用户执行
return effectFn
}
测试一波
const state = reactive({
a: 1,
b: 2,
c: 3,
});
// 有没有很像计算属性的感觉
const sum = effect(() => {
console.log("执行计算"); // 调用sum函数后被打印
const value = state.a + state.b;
return value;
}, {
lazy: true
});
// 不执行sum函数,effect注册的回调将不会执行
console.log(sum()); // 3
2. 依赖追踪
咱们初步实现了懒执行的特性,为了更像computed一点,我们需要封装一个函数。
function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
})
const obj = {
get value () {
return effectFn()
}
}
return obj
}
这就有点那么味道啦!
测试一波
可以看到computed只会依赖state.a和state.b,而不会依赖state.c,这得益于我们前面几篇文章实现的响应式系统,所以到了计算属性这里,我们不用改动任何代码,天然就支持。
不过还是有点小问题,我们读取了两次sum.value,sum却被执行了两次,这和computed缓存的特性就不符了。
别急,马上就要实现了这个最重要的特性了。
const state = reactive({
a: 1,
b: 2,
c: 3
})
const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
})
console.log(sum.value)
console.log(sum.value)

3. 缓存
回顾一下computed的缓存特性:
- 只有当其依赖的东西发生变化了才需要重新计算
- 否则就返回上一次执行的结果。
为了缓存上一次计算的结果,咱们需要定义一个value变量,现在的关键是怎么才能知道其依赖的数据发生变化了呢?
function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
})
let value
let dirty = true
const obj = {
get value () {
// 2. 只有数据发生变化了才去重新计算
if (dirty) {
value = effectFn()
dirty = false
}
return value
}
}
return obj
}
测试一波
const state = reactive({
a: 1,
b: 2,
c: 3
})
const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
})
console.log(sum.value) // 3
console.log(sum.value) // 3
state.a = 4
console.log(sum.value) // 3 答案是错误的
寄上任务调度
不得不说,任务调度实在太强大了,不仅仅可以实现数组的异步批量更新、在computed和watch中也是必不可少的。
function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
// 数据发生变化后,不执行注册的回调,而是执行scheduler
scheduler () {
// 数据发生了变化后,则重新设置为dirty,那么下次就会重新计算
dirty = true
}
})
let value
let dirty = true
const obj = {
get value () {
// 2. 只有数据发生变化了才去重新计算
if (dirty) {
value = effectFn()
dirty = false
}
return value
}
}
return obj
}
测试一波
const state = reactive({
a: 1,
b: 2,
c: 3
})
const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
})
console.log(sum.value) // 3
console.log(sum.value) // 3
state.a = 4
console.log(sum.value) // 3 答案是错误的
完美!!!这下面试官再也难不倒我了!!!

本文转载于:
https://juejin.cn/post/7259405321020424251
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--为啥面试官总喜欢问computed是咋实现的?的更多相关文章
- 基础面试,为什么面试官总喜欢问String?
关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String 在 Java 中,我们有两种方式创建一个字符串 String x ...
- 一线大厂面试官最喜欢问的15道Java多线程面试题
前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...
- 2019年面试官最喜欢问的28道ZooKeeper面试题
前言 ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务.它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护.域名服务.分布式同步.组服务等. ZooKeeper 的 ...
- 深度分析:面试腾讯,阿里面试官都喜欢问的String源码,看完你学会了吗?
前言 最近花了两天时间,整理了一下String的源码.这个整理并不全面但是也涵盖了大部分Spring源码中的方法.后续如果有时间还会将剩余的未整理的方法更新到这篇文章中.方便以后的复习和面试使用.如果 ...
- 阿里面试官最喜欢问的21个HashMap面试题
1.HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过 8 时,链表转换为红黑树. transient Node<K,V>\[\ ...
- 聊聊CAS - 面试官最喜欢问的并发编程专题
什么是CAS 学习Java并发编程,CAS(Compare And Set)机制都是一个不得不掌握的知识点.除了通过synchronized进行并发控制外,还可以通过CAS的方式控制,大家熟悉的Ree ...
- 2021超详细的HashMap原理分析,面试官就喜欢问这个!
一.散列表结构 散列表结构就是数组+链表的结构 二.什么是哈希? Hash也称散列.哈希,对应的英文单词Hash,基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出 这个映射的规则就是对 ...
- 走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串
原文:走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串 对大量数据进行查询时,可以应用到索引技术.索引是一种特殊类型的数据库对象,它保存着数据表中一列或者多列的排序结果,有 ...
- Java面试官最常问的volatile关键字
在Java相关的职位面试中,很多Java面试官都喜欢考察应聘者对Java并发的了解程度,以volatile关键字为切入点,往往会问到底,Java内存模型(JMM)和Java并发编程的一些特点都会被牵扯 ...
- 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)
大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式) 现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一 ...
随机推荐
- vue-element-admin iframes 组件 保留 iframe 操作状态
由于没有时间去维护这个功能,这个仓库我暂停了,当前博客内容和代码只作为实现思路参考 代码贴前面,gitee地址:https://gitee.com/chkhk/vue-element-admin 可以 ...
- Windows OhmGraphite 配置
Windows OhmGraphite 配置 由于windows_exporter无法监控温度相关的指标,那么就需要使用OhmGraphite进行监控该指标. 下载 访问 https://github ...
- 介绍 ComPDFKit 转换 SDK 1.5.0
介绍 ComPDFKit 转换 SDK 1.5.0 了解有关 ComPDFKit PDF SDK 的更多信息:https ://www.compdf.com/ ComPDFKit Conversion ...
- 【Unity3D】发射(Raycast)物理射线(Ray)
1 前言 碰撞体组件Collider 中介绍了 2 个碰撞体之间的碰撞检测,本文将介绍物理射线与碰撞体之间的碰撞检测.物理射线由 Ray 定义,通过 Physics.Raycast / Physi ...
- golang在 ubuntu下交叉编译报错 gcc: error: unrecognized command line option ‘-mthreads’; did you mean ‘-pthread’?
前置说明: 之前一直都是用centos 7做开发机, 因为工作需要用c2 工具sliver编译木马而依赖 mingw64,但是centos安装这个非常麻烦, 就换了ubuntu开发机; 现需要交叉编译 ...
- 细说Spring Boot初始化DispatcherServlet
DispatcherServlet概述 在Spring Boot框架未出现之前,要开发一个基于Spring MVC框架的项目,通常需要在Java web项目的描述符文件web.xml中添加如下配置: ...
- 海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储
前言 Hik防爆摄像头录像,因为防爆摄像头会有对应的APP软件,与普通的网络摄像头和球机不一样,默认认为它不可以通过web网页配置,所以弄了个来实测确认. 经测试实际上也是可以通过web网页配置 ...
- 【Azure 应用服务】App Service 默认页面暴露Tomcat版本信息,存在安全风险
问题描述 在创建Azure App Service时,服务端的配置使用Java 8 + Tomcat 8.5.默认的根目录页面显示出App Service Tomcat版本信息,存在一定的安全隐患. ...
- Task Manager 的设计简述
讲解 Task Manager 之前,在这里先介绍一些 Task Manager 会使用到的概念术语. 图数据库 Nebula Graph 中,存在一些长期在后台运行的任务,我们称之为 Job.存储层 ...
- linux 命令行使用codeql
目录 CodeQL 概述 安装 直接使用在线查询(lgtm) vscode使用codeql 下载 库文件 测试 linux控制台运行 下载 安装 创建数据库 编写QL查询数据库 简单解释 CodeQL ...
