如何理解js中基本数据类型的值不可变

2023-11-02

js的数据类型

  • 在讲解我们要说明的问题之前,需要知道js有哪些数据类型。js有两种数据类型:基本数据类型和引用数据类型

  • 基本数据类型:number、string、boolean、undefined、null、symbol

    在 Java 中,字符串是引用类型

  • 引用数据类型:Array、Function、Object 等

堆和栈

  • 程序运行的时候,需要内存空间存放数据。一般来说,系统会划分出两种不同的内存空间:一种叫做堆(heap),另一种叫做栈(stack)

  • 堆(heap)是没有结构的,数据可以任意存放,它是用于存放复杂数据类型(引用类型)的,例如数组对象、object对象等。

  • 栈(stack)是有结构的,每个区块按照一定次序存放(后进先出),栈中主要存放的是基本类型的变量的值以及指向堆中的数组或者对象的地址,存在栈中的数据大小与生存期必须是确定的。除此之外,还可以明确知道每个区块的大小,因此,stack的寻址速度要快于heap

    另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享

    假设我们同时定义 int a = 3; int b = 3;,编译器先处理 int a = 3:

    首先它会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 3 的地址,没找到,就开辟一个存放 3 这个字面值的地址,然后将 a 指向 3 的地址

    接着处理 int b = 3;,在创建完 b 的引用变量后,由于在栈中已经有 3 这个字面值,便将 b 直接指向 3 的地址。这样,就出现了 a 与 b 同时均指向 3 的情况

    特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化

    相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完 a 与 b 的值后,再令 a=4;,那么,b 不会等于 4,还是等于 3

    在编译器内部,遇到 a=4; 时,它就会重新搜索栈中是否有 4 的字面值,如果没有,重新开辟地址存放 4 的值;如果已经有了,则直接将 a 指向这个地址。因此 a 值的改变不会影响到 b 的值

  • 栈创建的时候,大小是确定的,如果超出了浏览器规定的栈限制,就会报 stack overflow 错误,而堆的大小是不确定的,需要的话可以不断增加。下面看一个简单的测试:

    var i = 0;
    function inc() {
        i++;
        if(i > 41909) {
        	return;
        }
        inc();
    }
    inc();
    

    测试环境是 16G 内存的电脑,需要注意的是:根据栈的定义可以知道如果 inc 函数里有变量声明的话也是会有内存占用的
    1、谷歌浏览器chrome 55.0版本下限制是41909条
    2、IE8浏览器下限制是3062条

  • 易犯的错误:

    var str=new String('abc');
    var str='abc';
    

    同样是创建两个字符串,第一种是用new关键字来新建String对象,对象会存放在堆中,每调用一次就会创建一个新的对象;而第二种是在栈中,栈中存放值‘abc’和对值的引用。推荐使用第二种方式创建多个’abc’字符串,这种写法在内存中只存在一个值,有利于节省内存空间。同时它可以在一定程度上提高程序的运行速度,因为存储在栈中,其值可以共享,并且由于栈访问更快,所以对于性能的提高大有裨益。而第一种方式每次都在堆中创建一个新的String对象,而不管其字符串值是否相等及是否有必要创建新对象,从而加重了程序的负担。并且堆的访问速度慢,对程序性能的影响也大

什么叫做“js中基本数据类型的值不可变”

  • 如果一个变量是基本数据类型,那么在它被赋值之后,这个值就是不可变的

常见疑惑

  1. number 类型。下面的代码为什么输出是 2 ?请结合所有的示例一起理解

    var a = 1;
    a = 2;
    console.log(a); //2
    
  2. string 类型。下面的代码为什么输出是 helloworld ?请结合所有的示例一起理解

    var str = "hello";
    str += "world";
    console.log(str); //helloworld
    
  3. string 类型。下面的示例1的代码为什么不能改变字符串的值?示例2为什么又可以改变?

    //示例1
    var myStr = "Bob";
    myStr[0] = "J";
    console.log(myStr); //Bob
    
    //示例2
    var myStrNew = "Bob";
    myStrNew = "Job";
    console.log(myStrNew); //Job
    
  • 不管你能不能理解下面所说的,请先记住这个结论:在 JavaScript 中,字符串的值是不可变的,这意味着一旦字符串被创建就不能被改变

  • 从结果来看,变量 myStr 的值并没有变成 Job,而 myStrNew 的值却变成了 Job

  • 首先要说明的是,因为字符串的数组行为不标准,所以应该避免使用它。因此对字符串类型的变量,使用下标的形式来取得其中的某个字符本来就是不规范的,最正确的做法是使用 charAt(index) 方法。另:

    当 index 的取值不在 str 的长度范围内时,str[index] 会返回 undefined,而 charAt(index) 则返回空字符串

    str[index] 不兼容 ie6-ie8,charAt(index) 可以兼容

    使用 中括号[] 的方式,不容易区分这个变量是字符串还是数组

  • 而对于示例2,我们要清楚,虽然有前面的那个结论,但结论中所说的不能改变指的是字符串字面量(string literal)的各个字符不能被改变

  • 针对字符串变量,有很多方法都可以应用在其上面,这些所有的方法看上去返回了一个修改后的字符串,实际上返回的是一个新的字符串值

  • 如果我们要 “改变” 某个字符串变量的值,唯一的方法是重新给它赋一个值,在示例2的赋值过程中,改变的其实只是 myStrNew 的指向(可以把 myStrNew 理解为指向 Bob 这个字符串字面量的指针)而 Bob 这个字符串字面量自始至终都没有被改变,至于它是在何时被垃圾回收机制回收的,博主也不敢确定,如果有知道的同学,请留言告知,不甚感激!

【附】

  • 用 const 定义的变量是不能改变的,这里其实分两种情况:如果定义的是基本数据类型的变量,那么的确是不能对其做任何操作来改变其值的;但如果定义的是引用类型的变量,由前面的分析可知,这个变量存储的其实只是一个地址,也就是说我们不能改变的是这个地址,但是地址中的内容我们还是可以改变的
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何理解js中基本数据类型的值不可变 的相关文章

随机推荐

  • 神经元是多输入单输出吗,单输入单输出神经网络

    1 人工神经网络的知识表示形式 人工神经网络的知识表示形式 1 每个神经元都是一个多输入单输出的信息处理单元 2 神经元输入分兴奋性输入和抑制性输入两种类型 3 神经元具有空间整合特性和阈值特性 4 神经元输入与输出间有固定的时滞 主要取决
  • 关于博客积分规则,总是找不着入口

    博客积分规则 博客积分是CSDN对用户努力的认可和奖励 也是衡量博客水平的重要标准 博客等级也将由博客积分唯一决定 积分规则具体如下 1 每发布一篇原创或者翻译文章 可获得10分 2 每发布一篇转载文章 可获得2分 3 博主的文章每被评论一
  • 微信小程序从入坑到放弃二十五:记一次在WXS中使用正则表达式的坑

    摘要 WXS WeiXin Script 是小程序的一套脚本语言 结合 WXML 可以构建出页面的结构 在此次开发中 由于接口返回数据不统一 所以要对某些字段进行过滤 但直接使用replace时竟然报错了 原来在WXS中要生成regexp对
  • 网络编程day3作业

    tftp下载 include
  • 【NLP】第 3 章 :BERT

    在本章中 您将学习由 Google 开发的 Transformer 架构的实现之一 称为 BERT Google AI Language 的研究人员最近所做的工作导致发表了一篇名为 BERT 来自变形金刚的双向编码器表示 的论文 BERT取
  • 模拟get和post请求

    一 模拟请求 浏览器及工具模拟 http请求有很多种 常用的请求方式有两种 get请求和post请求 今天先介绍浏览器以及工具模拟请求 下次会介绍代码模拟 1 get请求格式 url param1 value1 param2 value2
  • 阿里云OSS使用Java上传文件

    一 准备工作 1 1登录阿里云点击对象存储OSS 1 2 先点击Bucket 列表 在点击创建Bucket 1 3 根据自己需求勾选 然后点击确定 1 4 新建好之后 点击bucket名称 1 5 点击文件管理 1 6 在这个页面就可以实现
  • 常用正则表达式

    英文单词 public static final String REGEX WORD EN w 中文 public static final String REGEX WORD CN u4E00 u9FA5 6到30位 数字 字符 常用于用
  • 解决windows 您没有权限访问\\192.168.1.X(局域网) 请与网络管理员联系请求访问权限

    解决windows 您没有权限访问 192 168 1 X 局域网 请与网络管理员联系请求访问权限 今天哥们发来一张图 就是下图 说无法访问局域网内的数据了 这个问题咋处理 那就重头说这个事儿 先写一篇这个问题 正好本博客内还木有 出现这个
  • QueryWrapper查询查询时间空值排序空值放在最后

    代码如下 QueryWrapper
  • RFID智能汽车制造管理系统解决方案

    RFID智能汽车制造管理系统解决方案 1 项目背景 1 1 行业背景 在汽车行业快速发展竞争日益激励的背景下 各个汽车制造商都在追求管理系统的优化 已从开始的只追求最终结果的最优 发展到目前要求使制造汽车的每个环节都达到最优的目的 这就给管
  • 图像处理之卷积模式及C++实现

    1 卷积的三种模式 深度学习框架中通常会实现三种不同的卷积模式 分别是 SAME VALID FULL 这三种模式的核心区别在于卷积核进行卷积操作的移动区域不同 进而导致输出的尺寸不同 我们以一个例子来看这三种模式的区别 输入图片的尺寸是5
  • 服务器iis如何开启tlsv1.2协议,利用IIS Crypto V3.2开启IIS服务器TLS1.2的具体操作流程...

    今天客户给我反馈了一个在网站安装SSL证书后 网站https显示异常的问题 就是在谷歌浏览器下 会提示 您的连接存在安全隐患 访问被阻止 如下 如果继续强制浏览 会提示 你与此网站之间建立的连接并非完全安全 攻击者可能能够看到您正在此网站上
  • Command Prompt 常用命令

    一 CD Change Directory 改变现在指向的文件夹 1 去到最根的目录 cd 例如去到C盘 2 去某一文件夹 例如去C盘的logs文件夹 cd windows logs 3 返回上一级文件夹 cd 二 指向去另一个盘 指向另一
  • 解决PCCAD出现的致命错误Unhandled Access Violation ....

    最近公司电脑貌似很多的员工在打开pccad里面的TK的时候出现如下的界面 于是就开始认为是office的问题 在卸载了office之后 问题是解决了 不过总不能不叫员工使用office软件吧 于是乎不得不又装上了office 但是不是off
  • AD20-DRC检查

    点击下图中的红圈内选项 就会出现 第一个红圈可不勾选 可以不创建报告文件 第二个红圈中的填的稍微大一点 接下来就是 红圈中是安全间距检查 勾选可以检查板子中的安全间距 之后点击左下角的运行DRC 就行了 板子中有错误的话就会报错 有错改错就
  • adopt_lock 和 defer_lock 的区别

    c 中 lock guard 通过 raii 机制实现了自动上锁和解锁互斥量 基本用法为 static std mutex io mutex std lock guard
  • IDEA如何添加多Git源

    一 添加多Git源 选择IDEA顶部VCS菜单 再选择Git 点击Remotes 然后弹窗中点击 号添加 再弹窗中输入名字和git的地址 最后点击OK 另外一个Git源就加进来了 二 如何添加新的Git源的远程分支 选择IDEA顶部VCS菜
  • java搜索文本内容_JAVA 搜索文本文件中的关键字

    原文链接 http blog net blog abel article details 40858245 用JAVA实现对文本文件中的关键字进行搜索 依据每一行 得到每一行中出现关键词的个数 使用java io LineNumberRea
  • 如何理解js中基本数据类型的值不可变

    js的数据类型 在讲解我们要说明的问题之前 需要知道js有哪些数据类型 js有两种数据类型 基本数据类型和引用数据类型 基本数据类型 number string boolean undefined null symbol 在 Java 中