记录--为啥面试官总喜欢问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 替换标签的做法.一 ...
随机推荐
- Linux中如何查找特定的数据是否在目录或文件中
一个很简单的方式就是使用grep命令,grep命令是一个强大有效可靠并且很流行的命令行工具,用于查找对应的数据包含文件或者目录中在Linux环境中. 为了便于学习,我们准备了以下文件,具体想要查找以实 ...
- 实现阿里云模型服务灵积 DashScope 的 Semantic Kernel Connector
Semantic Kernel 内置的 IChatCompletionService 实现只支持 OpenAI 与 Azure OpenAI,而我却打算结合 DashScope(阿里云模型服务灵积) ...
- Oracle insert all语句介绍
Oracle 中insert语句的高级用法,INSERT ALL 语句介绍: 1.无条件insert all 全部插入 CREATE TABLE t1(product_id NUMBER, produ ...
- 【笔记】css —— BFC 原理
一.什么是 BFC BFC 即 Block Formatting Contexts (块级格式化上下文),具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素 ...
- python枚举之Enum模块
枚举是与多个唯一常量值绑定的一组符号(即成员).枚举中的成员可以进行身份比较,并且枚举自身也可迭代. 枚举成员名称建议使用大写字母 # 示例 from enum import Enum,unique, ...
- Xilinx GTH 简介 ,CoaXpress FPGA PHY 部分
什么是GTH GTH 是Xilinx UltraScale系列FPGA上高速收发器的一种类型,本质上和其它名称如GTP, GTX等只是器件类型不同.速率有差异:GTH 最低速率在500Mbps,最高在 ...
- 【Azure Kubernetes】通过 kubelogin 进行非交互式登录AKS
问题描述 当对AKS的登录方式(认证和授权)从"Local Account with Kubernetes RBAC "改变为"Azure AD authenticati ...
- 图查询语言 nGQL 简明教程 vol.01 快速入门
本文旨在让新手快速了解 nGQL,掌握方向,之后可以脚踩在地上借助文档写出任何心中的 NebulaGraph 图查询. 视频 本教程的视频版在B站这里. 准备工作 在正式开始 nGQL 实操之前,记得 ...
- 调试 Docker 容器内部进程
首发于官方博客:https://nebula-graph.com.cn/posts/debug-nebula-graph-processes-docker/ 摘要:本文以 Nebula Graph 进 ...
- 详解Python中sys模块的功能与应用
本文分享自华为云社区<深入Python:sys模块的功能与应用详解>,作者: 柠檬味拥抱. 在Python的标准库中,sys 模块是一个常用而强大的工具,它提供了与Python解释器交互的 ...
