《你不知道的Javascript系列》——不可变性immutable

news2024/11/26 20:35:25

基础

JavaScript中存在以下数据类型:

  1. 原生(基本)类型 —— Boolean, Number, String
  2. 非原始(引用)类型或对象 —— Object, Array, Function
  3. 特殊 —— Null, Undefined

原生数据类型默认是不可变的,对于常量声明的原生类型,他们值是不可变的,若用变量声明,虽然可以用=改变其值,实际上是重新赋值,仍没有改变内存地址所存的值,以下面代码为例:

let var1 = 'apple' //'apple' is stored in memory location A
var1 = 'orange' //'orange' is stored in memory location B

const var2 = 'apple'
var2 = 'orange' // ERROR: Re-assignment not allowed for constants

在上述例子中,如果我们修改 var1 这个 string,JavaScript 将会在内存中的另一个位置创造另一个 string,而 var1 将会指向这个新的内存位置,这被称为 重新赋值

因此重新赋值并不代表其为可变的,所有原生类型均为不可变的,这也就是为什么string类型的方法均会返回新的string,而不是改变原来的string。

对于非原始类型来说,是可变的。比如下面这段代码,改变了profile1指向的内存中的数据的属性:

const profile1 = {'username':'peter'}
profile1.username = 'tom'
console.log(profile1) //{'username':'tom'}

--------------------------------------------------
const sampleprofile = {'username':'name', 'pw': '123'}
const profile2 = sampleprofile

profile2.username = 'harry'

console.log(profile2) // {'username':'harry', 'pw': '123'}
console.log(sampleprofile) // {'username':'harry', 'pw': '123'}

并且JavaScript是引用传递的(通过=将sampleprofile的引用传递给了profile2,此时二者指向的是内存中的同一数据),因此修改一个另一个也会修改。

理解

对于mutable(可变)和immutable(不可变)来说,本质区别在于变量指向的内存地址数据能否被修改。

  • 以immutable类型来说,用=重新赋值后,内存中的实际数据是不可修改的,只是重新在新的内存地址创建新的值,然后改变指针的指向
  • 以mutable类型来说,内存中的实际数据是可以被修改的,因此重新赋值后,二者所指的数据都发生了变化。

为了防止修改mutable类型的数据,有两种解决方案:

  • 通过冻结对象来防止修改
  • 使用浅拷贝和深拷贝

let 与 const

变量与常量,对常量来说,指的是指向的数据的内存地址指针不可变,而对变量来说,指针地址是可以变化的。

防止修改对象

freeze

使用 Object.freeze() 。它的作用是,防止对象已有的属性被改变。任何改变的尝试都会静默失败,意味着它不会成功,也不会有任何警告。不过是一种浅冻结,即它对于深层嵌套的对象将不会有用。

const sampleprofile = {
  'username':'name',
  'pw': '123',
  'particulars':{'firstname':'name', 'lastname':'name'}
}

Object.freeze(sampleprofile)

sampleprofile.username = 'another name' // no effect

sampleprofile.particulars.firstname = 'changedName' // changes

拷贝

浅拷贝

扩展操作符...

所有对象的属性将被合并在一起,但对于冲突的属性,后展开的对象有更高的优先级。

const profile1 = {'username':'name', 'pw': '123', 'age': 16}
const profile2 = {'username':'tom', 'pw': '1234'}
const profile1Copy = {...profile1}
const resultProfile = {...profile1, ...profile2}

console.log(profile1Copy) // {'username':'name', 'pw': '123', 'age': 16}
console.log(resultProfile) // {'username':'tom', 'pw': '1234', 'age': 16}

Object.assign()

类似于扩展操作符

Array.slice()

浅克隆数组的一个便捷方法

const firstSet = [1, 2, 3];
const firstSetCopy = firstSet.slice()

console.log(firstSetCopy) // [1, 2, 3]

//note that they are not the same objects
console.log(firstSet===firstSetCopy) // false

深拷贝

使用 JSON.stringify() 和 JSON.parse()

JSON.parse(JSON.stringfy({}))

使用 lodash.deepclone()

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

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

相关文章

好消息FL Studio21.2中文版本发布了!新功能详细介绍

为庆祝 FL Studio 21.2 的发布,所有 FL Studio 用户都可免费使用一个月的 FL Cloud。只需打开 FL Studio 21.2,点击浏览器中的 "声音 "标签即可开始使用。FL Cloud 提供完全集成的采样库、人工智能母带处理和由 DistroKid 支持的数字发行&…

bbr 流相互作用图示

类似 AIMD 收敛图,给出 bbr 的对应图示: bbr 多流相互作用非常复杂,和右下角的 AIMD 相比,毫无美感,但是看一眼左下角的 bbr 单流情况,又过于简陋,而 bbr 的核心就基于这简陋的假设。 浙江温…

【rust/esp32】在idf中使用embedded-graphics控制st7789 LCD屏幕

文章目录 说在前面模块详情准备工作开始编译烧录结果 说在前面 esp32版本:s3运行环境:esp-idf(std)开发环境:wsl2LCD模块:ST7789V2 240*280 LCDgithub地址:这里 模块详情 某宙的esp32s3开发板 某雪的1.69inch LCD模块…

78 子集

子集 题解1 回溯模板 题解2 迭代(mask思想) 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入…

AcWing 第127场周赛 构造矩阵

构造题目,考虑去除掉最后一行最后一列先进行考虑,假设除了最后一行和最后一列都已经排好了(你可以随便排),那么分析知最后一个数字由限制以外其他都已经确定了,无解的情况是k为-1 并且n,m的奇偶…

网络编程套接字(1)——简单的UDP网络程序

文章目录 一.预备知识1.理解源IP地址和目的IP地址2.理解源MAC地址和目的MAC地址3.理解源端口号和目的端口号4.PORT VS PID5.认识TCP协议和UDP协议6.网络字节序 二.socket编程接口1.socket常见API2.sockaddr结构 三.简单的UDP网络程序1.服务端创建套接字2.服务端绑定3.字符串IP …

ctf md5爆破

1.知道组成的字符为数字,然后知道加密后的MD5,求组成的字符 import hashlibimport stringdef crackMd5(dst):dst dst.lower()for a in range(0,10):for b in range(0,10):for c in range(0,10):for d in range(0,10):word str(a) str(b) str(c) str(d) "_heetian&q…

【报错】kali安装ngrok报错解决办法(zsh: exec format error: ./ngrok)

问题描述 kali安装ngrok令牌授权失败 在安装配置文件的时候报错:zsh: exec format error: ./ngrok 原因分析: 在Kali Linux上执行./ngrok时出现zsh exec格式错误的问题可能是由于未安装正确版本的ngrok或操作系统不兼容ngrok导致的。以下是一些可能的解…

k8s安装时初始化报错:error execution phase preflight

服务器配置与k8s版本 系统版本: CentOS Linux release 7.9.2009 (Core)内核版本: [rootk8s-node02 tmp]# uname -r 5.4.259-1.el7.elrepo.x86_64k8s版本 v1.15.1 [rootk8s-node1 tmp]# kubeadm version kubeadm version: &version.Info{Major:&q…

(免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐

摘 要 随着互联网趋势的到来,各行各业都在考虑利用互联网将自己推广出去,最好方式就是建立自己的互联网系统,并对其进行维护和管理。在现实运用中,应用软件的工作规则和开发步骤,采用Java技术建设农产品销售管理系统。…

人工智能(AI)在医疗领域的应用

人工智能(AI)在医疗领域的应用 人工智能(AI)在医疗领域的应用近年来得到了广泛的关注。其中,AI辅助治疗疾病的技术成为了研究热点。本文将介绍AI辅助治疗疾病的技术,包括其定义、应用场景、案例分析和发展…

jdk10的var局部变量类型推理

注:本人参考了openjdk官网,由于openjdk是开源的,所以不存在侵权行为,本章只为学习,我觉得没有什么比官网更具有话语权 1、jdk10的var的类型推测:就是这种处理将仅限于具有初始值设定项的局部变量、增强型 -…

Android问题笔记四十三:JNI 开发如何快速定位崩溃问题

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&…

opencv 滤波与blob检测总结

参考:https://learnopencv.com/contour-detection-using-opencv-python-c/ import cv2 impory numpy as np image cv2.imread(rxxx.jpg) # Sobel Edge Detection sobelx cv2.Sobel(srcimg_blur, ddepthcv2.CV_64F, dx1, dy0, ksize21) # Sobel Edge Detection o…

Python程序设计期末复习笔记

文章目录 一、数据存储1.1 倒计时1.2 os库1.3 字符串操作1.4 文件操作1.5 列表操作1.6 元组1.7 字典 二、文本处理及可视化2.1 jieba分词2.2 集合操作2.3 pdf文件读取2.4 参数传递2.5 变量作用域 三、数据处理分析3.1 Sumpy3.2 Matplotlib3.3 Numpy 四、Pandas4.1 索引操作4.2 …

【算法|动态规划 | 01背包问题No.1】AcWing 426. 开心的金明

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程&a…

Java Dubbo 微服务框架 HP-SOA

HP-SOA 功能完备,简单易用,高度可扩展的Java微服务框架。 【快速开始】 技术架构 技术集成 Web服务框架:spring-boot 3.x微服务框架:Dubbo 3.x服务注册中心:Nacos配置中心:Nacos服务治理中心&#xff1…

色彩校正及OpenCV mcc模块介绍

一、术语 1.光:是电磁波,可见光是可被人眼感知的电磁波。可见光大约在400-700nm波段。光子携带的能量与波长成反比,400nm--700nm之间的单色光的颜色从紫色渐变成红色。 2.光谱:除了太阳光源外,LED灯、白炽灯等各种照明…

基于Java的汉服文化平台网站设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

python随手小练10(南农作业题)

题目1: 编写程序,输出1~1000之间所有能被4整除,但是不能被5整除的数 具体操作: for i in range(1,1000): #循环遍历1~999,因为range是左闭右开if (i % 4 0) and (i % 5 ! 0) :print(i) 结果展示: 题目2&…