JavaScript进阶----《getter 和 setter 是什么》

news2024/10/5 16:24:23

前言: 这两个属性在学习前端的时候看到过,但是由于项目中没有用到过,所以一直没有细致的了解。今天 review 同事代码的时候,遇到了这个写法,看了半天也不知道如何处理。再不学习真的以后连别人的代码都不知道什么意思了。而后经过查阅 MDN 以后,颠覆了自己对 js 的基础知识 —“对象(object)” 的认知,并由此深感自己的不足。故今天来做一个简单总结,讲给同样在学习路上的你。

tips: 如果你是 react 开发,你可以选择直接跳跃至标题二开始阅读。如果你是 vue 开发,我强烈建议你从标题一开始阅读,你会更加有代入感的阅读本文。

因为作者主要是 vue 开发,本文的由来就是阅读同事的 vue 代码有感而作,但是也请 react 开发的同学不要害怕,没有标题一也并不会影响你阅读本文的整体感受🎁。

一. 初次相遇的场景

  1. 第一次遇到这两个名词的场景,是在学习 Vue3 教程的过程中,在看到 computed 的用法时,看到了下面这样一段描述:
    image.png
    原文链接:vue3 Computed 讲解

  2. 回顾一下我们在 vue3computed 常用的写法。我在项目中最常用的方法就是给 computed 传递一个回调函数, 这个回调函数返回值就是这个计算属性的值。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqFfVsVK-1688007173495)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/af7ff16637e04a37baaeeb0e63bbf7ec~tplv-k3u1fbpfcp-watermark.image?)]

  3. 随着写的项目越来越多,我逐渐形成了一个惯性思维,好像 computed 就是这样“仅此而已”。其实不然,它还有更进阶的用法,接下来让我们继续慢慢理解。

  4. 相信大家一定理解下面的代码为什么会报错。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-guD65dmV-1688007173495)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/79a9cbbd98494f77ada817b91c8f2d6f~tplv-k3u1fbpfcp-watermark.image?)]

  5. 因为我们上面是 computed 的基础用法,这样用其实你只给这个 name 这个属性设置了 getter。这样就导致了你这个 name 属性只能读取,而不能改写(或者叫做重新赋值)
    image.png

  6. 听到这里,你可能和最开始的我一样困惑。什么 getter? 我连单词 get 都没看见,你就在这里自言自语 getter,别急,一步一个脚印慢慢来。

  7. 仔细看我们上面的写法,我们如果只给 computed 函数一个函数作为参数。如下图:
    image.png
    那么其实上面的写法等价于下面的写法(tips:暂时忽略报错,这里的报错不是重点
    image.png

  8. 你可能更加好奇了,什么鬼,从哪里凭空冒出来一个 get? 为啥这样写就不能重新赋值了?在此之前你必须更加深入了解 object 这个类型。

二. object 属性的定义方法

  1. 这里我准备了一个空对象,现在我想让你给这个 obj 赋予一个叫做 name 的属性。值为字符串类型的 “韩振方”。你会怎么做?
    image.png

  2. 我觉得你甚至不需要思考,条件反射的都可以写出下面的代码。
    image.png

  3. 你要知道,其实这一步你是在完成一个对 obj属性描述过程

  4. 让我们完整的回顾上面的过程:你刚刚给 obj 这个对象添加了一个属性叫做 ‘name’,并且这个 name值(value) 是一个叫做 “韩振方” 的字符串。

  5. 接下来我将告诉你的是,在你 obj.name=“韩振方”的时候,你其实间接的调用了 Object 原型身上的 defineProperty 方法。

三. Object.defineProperty

  1. MDN 上查阅可知,这个函数有三个参数。
    image.png

  2. 让我换一种方法,重新写 obj.name=“韩振方” 这段代码,那么它其实等价于Object.defineProperty(obj,"name",{value:"韩振方",...})
    注意! 上面的代码不严谨,它省略了一部分内容。我只是想通过上面引出我们接下来要讲解十分重要的知识点属性描述符。 后面我会慢慢补充省略的内容。

  3. 由上面代码我们可以知道这个函数的基本用法,接收3个参数,第一个参数是要添加属性的对象(obj),第二个参数是要添加的属性名称(name),关键点是第三个属性,这个属性是一个对象类型的参数。我们的重点是搞清楚这第三个参数都有什么选项。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hSJhbWcW-1688007173497)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5c519fb5cfd24a80a09a0ab5af1366ee~tplv-k3u1fbpfcp-watermark.image?)]

  4. 由于篇幅限制,在本文中,我们暂时忽略“enumerable”和“configurable”这两个属性。我们重点看下面这几个属性。
    image.png

  5. 在讲解下面的知识之前,我想再强调一下,第三个参数属性描述符 是一个对象类型,{}它有且只有一些固定的键值对。它用来约束这个即将要定义的属性的一些行为。

四. value 和 writable

  1. value,我相信这个选项非常非常容易理解,就是你给这个属性即将赋予的值。

  2. 读懂了下面带红线的句子,你应该就明白了一个没有赋值的属性是为什么值是 undefined 的了吧?
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S06U9Aog-1688007173497)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/728e5e5c14974d90a42184912ec44cfe~tplv-k3u1fbpfcp-watermark.image?)]

    image.png

  3. writable 是否可写,这里可写说白了就是是否可以重新被赋值。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9FPaavn-1688007173497)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5cc9beaa57e9480db0879b27df5d26eb~tplv-k3u1fbpfcp-watermark.image?)]

  4. 强调一下这里 writbale 默认值不是我们想象中的 true 而是 false

  5. 回顾我们上面的代码。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PX4rSwS7-1688007173497)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/25909a2ff5094ba184b6eab34e917f2f~tplv-k3u1fbpfcp-watermark.image?)]
    由于我们没有定义 writable ,所以按道理来讲它是不可重新赋值的。 让我们验证一下:
    不出所料,控制台报错了,并且报错信息和猜测的一样,不能给只读属性赋值。
    image.png

  6. 让我们设置 writabletrue 再重新尝试一下。
    image.png
    可以看到控制台的错误没有了,并且正确输出了修改过后的值。
    image.png

  7. 别忘了,刚刚我们重新赋值的代码,obj.name="小韩" 这一步本质上还是在重复使用 Object.defineProperty 这个函数。正好也对应了 MDN 的这段解释。
    image.png

五. getter 和 setter

  1. 标题的内容终于到了,其实 gettersetter 并没有那么难理解。

  2. 首先让我们搞明白一个过程。下面的代码是在控制台输出 objname 属性的值。对吧?
    image.png

  3. 其实你的这个动作 obj.(注意有个点)obj点 的过程是在“读取obj 对象的 name 属性。注意这个 “读取” 的动作。这个读取其实就是对应了获取 value 的过程。
    image.png

  4. 这个动作正好就是 getter 要做的行为。首先别看叫 getter 就很害怕,它其实就是属性描述符的一个属性 get 而已,仅此而已。只不过这个属性的值是一个函数。起了个外国人名字,加了个 er 叫起来顺口而已。

  5. 什么?有点绕?还不懂?一个普通对象,有一个属性,属性值是一个函数。像下面,一个对象 hanzhenfang ,有一个属性叫做 skill,值是一个函数,能够被执行,执行后在控制台输出一个哈哈
    image.png
    怎么我这样写你就能明白,换个说法就不明白了呢?

  6. 回到 getter,我想你可能马上想到 getter 的用法应该像下面这样。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NnLAeyUT-1688007173498)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b48facfa1c704020888f8622e31d95fc~tplv-k3u1fbpfcp-watermark.image?)]
    对不起,这样是不允许的,因为 get 属性的返回值将会被作为属性值的读取结果给你。这样会造成编译器无法知道你的像 obj.name 这样的属性值读取过程该返回给你哪一个值。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BtZvFggW-1688007173498)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/590b410b05d2440a95f0387fde9dd7e3~tplv-k3u1fbpfcp-watermark.image?)]

  7. 你只把 value 去掉也是不可以的,因为 writable 对应我们马上要讲的 setter
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZXYnpbHO-1688007173498)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c8b55c315c014a3abb4ce8a48eb678b7~tplv-k3u1fbpfcp-watermark.image?)]
    image.png

  8. 所以正确的 gettr 用法是下面这样。
    image.png
    image.png

  9. 让我们不设置 setter,尝试把 name 修改回 韩振方 试一下。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xhbSbM0I-1688007173499)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6d831f02ba384432b1b93e63e2c4aaeb~tplv-k3u1fbpfcp-watermark.image?)]
    有了上面的 writable 的经验,我们大概率要翻车。果然控制台报错了,“你不能给一个只有 getter 的对象属性重新赋值。”
    image.png

  10. 聪明的你一定想到了下面的结论,没错, getter 对应的是 value ,而setter 对应的正是 writable

  11. setter 也是一个值为函数的属性,不过这个属性接收一个参数,这个参数正是赋值运算符右边的内容。(也就是等号右边的值)千万一定要仔细看我们下面的写法。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pq37cNnv-1688007173499)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b9d7bea116542aa8d17486fb0442e46~tplv-k3u1fbpfcp-watermark.image?)]

  12. 我们仅仅在 setter 函数的内部打印了一下新的值,而并没有对新的值做任何操作,那么其实我们 objname 属性仍为数字 10
    image.png
    验证一下:
    image.png

  13. 为什么要这样做呢?我举个简单的例子,这样会给我们一个十分重要的中间处理步骤。假设我在给 obj 重新命名。因为我姓,你改的名字里姓氏最起码得是才可以通过吧?你直接改成吴彦祖那不乱拉套了?
    image.png
    可以看到我们可以在 setter 正确拦截错误的操作。
    image.png

  14. 请原谅我啰嗦一大堆,因为我想如果像上面这样用实际例子演示可能会比 MDN 这样一段大白话更加通俗易懂。
    image.png

六. 重新分析 computed

回过头再看我们标题一的问题就显得十分清晰了。
image.png
image.png

七. 思考题

gettersetter 有一个经典的错误使用案例。请分析为什么下面的代码会引起递归导致栈溢出?
image.png
控制台输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njikwhbo-1688007173500)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a3df9c48472420f89285f0d62b6c302~tplv-k3u1fbpfcp-watermark.image?)]
image.png
如果你明白了上面代码报错的原因,我想你也就明白了 gettersetter 🎁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/698946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

报名 | AI驱动下的流程挖掘如何提升企业决策和运营效率?

随着人工智能(AI)技术的不断发展和普及,其在各个领域的应用也越来越广泛。其中,一项重要的应用就是利用AI技术驱动流程挖掘,以提升企业决策和运营效率。 流程挖掘是一种从事件日志中发现、监控和优化实际业务流程的技…

Elasticsearch 安装

下载安装 elasticsearch下载链接 运行:bin\elasticsearch.bat 设置密码:.\bin\elasticsearch-setup-passwords interactive 这边设置密码遇到一个坑 PS G:\elasticsearch-8.8.1> .\bin\elasticsearch-setup-passwords interactiveFailed to authe…

0基础学习VR全景平台篇 第52篇:高级功能-开场加载!

大家好,欢迎观看蛙色VR官方系列——后台使用课程! 本期为大家带来蛙色VR平台,高级功能-开场加载! 功能位置示意 一、本功能将用在哪里? 开场加载,指作品制作上线,观看者打开VR漫游作品首先看到…

机器学习技术(一)——python基础超详解

机器学习技术(一)——python基础超详解 文章目录 机器学习技术(一)——python基础超详解0、引言1、基础概念**:snake:变量****:snake:注释****:snake:输入 输出** 2、数据类型**:snake:数值类型****:snake:运算符****:snake:字符串…

直播预约 | 邀您共同探讨“云XR技术如何改变元宇宙的虚拟体验”

随着数字化时代的到来,元宇宙成为了人们关注的焦点。它是一个虚拟的世界,融合了现实与虚拟的元素,让人们可以以全新的方式进行交互、创作和体验。 云XR技术是元宇宙建设的重要支撑技术之一,元宇宙需要具备高度真实感、高度交互性…

7DGroup性能实施项目日记6

九月廿三 壬寅年 虎 庚戌月 甲辰日 全国在降温之际 不管如何,今天总算是执行起来了脚本。在配置了性能工具之Jmeter 后置监听器可视化数据逻辑的界面中,看到下图: 显然 TPS 在这个接口中能达到 1500 以上,这对第一次执行来说&am…

最优化--最大似然估计--最优化理论介绍

目录 最大似然估计 概念 最大似然估计原理 应用 最优化理论介绍 最优化问题 迭代求解 最大似然估计 概念 最大似然估计(Maximum Likelihood Estimation,MLE)是统计学中一种常用的参数估计方法。它基于观测数据,通过寻找…

win11禁止运行脚本的解除方法

win11使用Windows PowerShell执行脚本时,提示本系统上禁止运行脚本 解决办法(按照步骤进行): 先以管理员身份运行PowerShell。 命令行输入set-ExecutionPolicy RemoteSigned回车,然后输入Y回车即可。至此问题解决。若…

向量的傅里叶变换

note 若要求矩阵的傅里叶变换,则对每个行或列向量求对应的傅里叶变换。 比如matlab中对矩阵求fft傅里叶变换就是对每个列向量分别求傅里叶变换。 code /*\brief:离散傅里叶变换\param dir:变换方向,-1为傅里叶正变换,1为傅里叶反变换\param…

LLM - 第2版 ChatGLM2-6B (General Language Model) 的工程配置

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/131445696 ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,在保留了初代模型对话流畅、部署门槛较低等众多优…

逍遥自在学C语言 | 函数初级到高级解析

前言 函数是C语言中的基本构建块之一,它允许我们将代码组织成可重用、模块化的单元。 本文将逐步介绍C语言函数的基础概念、参数传递、返回值、递归以及内联函数和匿名函数。 一、人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 —— 自在…

python用flask将视频显示在网页上

注意我们的return返回值必须是以下之一,否则会报错 from flask import Flask, render_template, Response import cv2app Flask(__name__)app.route(/) def index():return render_template(index.html)def gen(camera):while True:success, image camera.read(…

组装电脑U盘重装Win10系统教程图解

当您需要对组装电脑进行重新安装Win10操作系统时,使用U盘是一种方便而有效的方法,U盘重装系统不仅可以帮助您解决各种系统问题,还能提供一个干净、稳定的系统环境。无论您是初学者还是有一定经验的用户,本教程将提供清晰的组装电脑…

人机环境系统智能能够解决以巴冲突吗?

巴以冲突的由来可以追溯到19世纪末和20世纪初,当时巴勒斯坦是奥斯曼帝国的一部分,但随着第一次世界大战的爆发,奥斯曼帝国在1917年被英国占领。在此后的几十年里,巴勒斯坦地区成为了犹太人和阿拉伯人之间争夺的焦点。在20世纪初&a…

K8s部署 Redis 主从集群

目录 ​编辑 一、环境准备 1.1 环境说明 1.2 安装说明 1.3 Redis集群说明 1)单实例模式 2)哨兵模式 3)集群模式 二、安装NFS 2.1 安装NFS 2.2 创建NFS共享文件夹 2.3 配置共享文件夹 2.4 使配置生效 2.5 查看所有共享目录 ​编…

PW系列wifi墨水屏标签操作指导

PW系列wifi墨水屏标签操作指导-V1.0 版本 操作人 操作 日期 V1.0 Kevin 创建 20220927 一、设备初始化 1.1.准备 向厂家获取一下信息: 服务器地址(MQTT地址) 操作账号 和操作账号绑定的(产品KEY) 1.2.安装wifi-tools工具 需要windows系统电脑并且有w…

【2022吴恩达机器学习课程视频翻译笔记】2.3监督学习-part-2

B站上面那个翻译我有点看不懂,打算自己啃英文翻译了(有自己意译的部分),然后懒得做字幕,就丢在博客上面了,2.2之前的章节结合那个机翻字幕能看懂 2.3监督学习-part-2 So supervised learning algorithms …

Linux vs MacOS ,你更喜欢哪个系统?

大家应该都知道Windows,Linux和MacOS这几个操作系统,它们各有优缺点,比如像游戏等专门的领域,Windows当然是比Linux更好些,但Linux是开源的,安全性和稳定性要比Windows要好,如果是关于视频编辑方…

蓝绿发布、灰度发布和滚动发布

当涉及到软件发布时,金丝雀发布(灰度发布)、滚动发布和蓝绿发布是常见的策略。它们各自有自己的优缺点、区别和特点。本文将简单介绍: 金丝雀发布(Canary Release) 金丝雀发布有一个有趣的小故事&#xff…

【算法】最长公共子序列编辑距离

文章目录 最长公共子序列(LCS)编辑距离(Edit Distance)总结相关题目练习583. 两个字符串的删除操作 https://leetcode.cn/problems/delete-operation-for-two-strings/712. 两个字符串的最小ASCII删除和 https://leetcode.cn/prob…