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 定义的变量是不能改变的,这里其实分两种情况:如果定义的是基本数据类型的变量,那么的确是不能对其做任何操作来改变其值的;但如果定义的是引用类型的变量,由前面的分析可知,这个变量存储的其实只是一个地址,也就是说我们不能改变的是这个地址,但是地址中的内容我们还是可以改变的

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

  1. 深入理解Js中的this

    深入理解Js中的this JavaScript作用域为静态作用域static scope,但是在Js中的this却是一个例外,this的指向问题就类似于动态作用域,其并不关心函数和作用域是如何声明以及 ...

  2. html数据类型判断,JS中判断数据类型的几种方法

    1⃣️首先我们来了解一下js中的数据类型 1.基本数据类型:Undefined.Null.Boolean.Number.String(值类型) 2.复杂数据类型:Object(引用类型) (值类型和引 ...

  3. 彻底理解js中this

    相关博文:http://blog.csdn.net/libin_1/article/details/49996815 彻底理解js中this的指向,不必硬背. 首先必须要说的是,this的指向在函数定 ...

  4. [转载] Java内存管理-你真的理解Java中的数据类型吗(十)

    参考链接: Java中的字符串类String 1 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 推荐阅读 第一季 0.Java的线程安全.单例模式.JVM内存结构等知识 ...

  5. 数据科学 IPython 笔记本 9.3 理解 Python 中的数据类型

    9.3 理解 Python 中的数据类型 本节是<Python 数据科学手册>(Python Data Science Handbook)的摘录. 译者:飞龙 协议:CC BY-NC-SA ...

  6. js中判断数据类型的方法

    JS中判断数据类型的方法: 使用typeof操作符. 对一个值使用 typeof 操作符可能返回下列某个字符串,返回的类型都是字符串形式. (1) undefined:如果这个值未定义 (2) boo ...

  7. 前端开发:JS中常用数据类型的转换以及使用场景集锦

    前言 在前端开发中,关于数据转换也是使用频率非常高的知识点,尤其是常见数据类型之间的相互转换的使用频率就更高了,那么本篇博文就来分享一下关于JS中常用数据类型的转换使用,分享一下,方便后期查阅使用. ...

  8. 理解js中this的指向

    彻底理解js中this的指向 JavaScript 的 this 指向问题深度解析 转载于:https://www.cnblogs.com/jeacy/p/6509616.html

  9. SpringMVC中通过@ResponseBody返回对象,Js中调用@ResponseBody返回值,统计剩余评论字数的js,@RequestParam默认值,@PathVariable的用法

    1.SpringMVC中通过@ResponseBody返回对象,作为JQuery中的ajax返回值 package com.kuman.cartoon.controller; import java. ...

最新文章

  1. 移动互联网时代之用户名和密码何去何从(1)
  2. css--css选择器,伪类
  3. JavaSE(十七)——IO流之字节流
  4. 关系型数据库和NOSQL的对比
  5. node mysql 模块 封装_node.js基于工厂方法的mysql模块封装
  6. 光电雷达智能跟踪平台
  7. Oracle的字符串转换成二进制,将二进制字符串解析为文本/字符
  8. 火遍日本 IT 界的「鱼书」终出续作,原来进阶深度学习竟然那么简单(文末赠书)...
  9. linux命令 选项,不点之Linux命令、选项及文件概念
  10. 软件工程中的十三种文档
  11. 当年,我为何关停了亲手创建的“北京圣思园”
  12. Android 救援模式(Rescue Mode)原理剖析
  13. jsp遍历List map
  14. RAR文件设置密码和清除密码的方法
  15. 新制式轨道交通有哪些?这篇推文全讲清了
  16. 【java多线程】多线程为什么跑的比单线程还要慢?!
  17. 一、CC2530开发环境搭建
  18. ML:机器学习模型的稳定性分析简介、常见的解决方法之详细攻略
  19. Ardunio开发实例-水银倾斜开关模块
  20. PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问

热门文章

  1. 常见的推荐算法原理介绍
  2. 练习:药店销售数据分析
  3. IDEA中拉取Bitbucket项目到本地
  4. 对称加密、非对称加密、混合加密
  5. 警觉室内点缀污染闻气味判别陷误区
  6. 安卓8.0以上系统如何没root激活xposed框架的步骤
  7. Angular4搭建在线可竞拍网站
  8. BAT与华为,谁将会是未来人工智能时代的主导?
  9. lorenz画图matlab,Matlab画Lorenz系统的最大李雅普诺夫指数图
  10. 2021年中国商品房市场供需现状分析,销售面积、销售额分别同比增长1.9%与4.8%「图」