JS----变量、常量及数据类型详解

2,122 阅读6分钟

前言

最近打算有空闲时间慢慢整理一些JS相关文章,先从变量、常量及数据类型入手。本文将重点围绕以下几点进行介绍:

  • 变量var和let、变量在内存中的具体存储形式
  • 常量const
  • 数据类型、typeof详解
  • 数据类型的显隐示转换
  • null和undefined的区别
  • js判断数据类型的方法

变量

JS中的变量是松散类型的,可以存储任何类型的数据。因此JS也称为弱类语言。JS变量松散类型的本质,决定了变量只是在特定时间用于保存特定值的一个名字而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变。过多基础概念不在赘述。

变量命名规则

  1. 变量名必须以英文字母、_、$开头
  2. 变量名可以包括英文字母、_、$、数字
  3. 不可以使用系统的关键字、保留字作为变量名

var变量

var定义的变量没有块级作用域,只有函数级作用域(作用域问题改天会更新详解)。当我们在JS中写下:

var a = 100;

这样的语句执行时实际上发生了两个步骤:第一步,申请一块内存空间叫做a,第二步,向此内存空间里赋值。因此,我们就能很清晰的理解以下两种情况:

  1. 如果只是声明变量没有赋值相当于只申请了一块内存空间,此时内存空间里没有实际值故系统显示为undefined。
  2. 如果未经声明的变量直接赋值是不安全的,尽管在非严格情况下可以运行,是因为js解释器帮你做了第一步申请,并且它会将这种未经声明的变量视为全局变量。而在严格模式下,系统会报Reference(非法或不能识别的引用类型)的错误。

let变量

let变量是es6中引进的,用let定义的变量会生成一个作用域,外部不能访问。因此对于变量的私有化要求更加严格。let定义的变量有以下几个特点:

  1. let定义的变量拥有块级作用域
  2. let在块级作用域中不存在变量提升
  3. 不能在同一作用域中(函数作用域和块级作用域)用let声明相同的变量

变量在内存中的具体存储形式

基本类型是保存在栈内存中的,它们的值都有固定的大小,保存在栈空间,按值访问。 引用类型保存在堆内存中,值大小不固定。栈内存中存放改变量的访问地址,地址指向堆内存中的对象。js不允许直接访问堆内存中的位置。

当基本类型变量发生复制行为时,系统会自动为新的变量分配一个新值,最后这些变量时独立互不影响的。而引用类型变量复制时,系统也会为新变量分配一个新值,不同的是,这个值也只是一个地址,指向的是堆内存中的同一个对象。因此a.x发生变化时b.x也会发生变化。如图

基本类型 image.png 引用类型 image.png

常量

const定义的是常量,不可以修改并且必须初始化。使用const定义数组时,数组名不能改变,但数组的内容可以通过push改变。因为数组内容的改变不会改变数组的引用地址。

数据类型

JS中的数据分为七种内置类型,这七种内置类型又分为两大类型,一种是原始值,一种是引用值。

原始值

  1. Number 数字类型
  2. String 字符串类型
  3. Boolean 布尔类型
  4. undefined 未定义
  5. null 空(占位值)
  6. symbol

五个原始值这里不在赘述。有一点需要注意的是原始值是栈数据。操作的是数据。

引用值

引用值有很多种,例如array,object,function,date...等,引用值是堆数据,操作的是存数据的内存地址。

typeof详解

typeof操作符返回的是一个字符串,字符串,字符串(重要的事情说三遍)用来指示未经计算的操作数类型。typeof是唯一一个使用未声明对象不会报错(会返回undefined)的操作符。它总共有六个返回值,需要牢记,分别是:

  1. Number
  2. Boolean
  3. String
  4. undefined
  5. object
  6. function

其中object为所有引用值的返回值。需要强调的一点是object同时也是null的返回值。这是由于最初null这个占位值用做空对象,浏览器一直把它当做对象看待。

数据类型的显隐示转换

显示类型转换(显示装箱)

  1. Number(需转换的数据)

Number(null);//0

Number(undefined);//NaN

  1. parseInt(需转换的数据,基底)

将数据根据基底要求的进制转换成十进制整型,基底的范围为2~36,只取小数点之前的数,不会进行四舍五入。

  1. parseFloat(String)

识别到第一个小数点后的所有数字类型并返回,遇到非数字类型就砍断。

  1. String(需转换的数据)

  2. Boolean(需转换的数据)

在js中undefined, null, false, NaN, '', 0, -0这些值都为false

  1. 需转换的数据.toString(基底);

需要注意undefined和null不能用此方法。这个里面的基底与上面不同,这里的基底是将调用它的数据转换成基底要求的进制数。

隐示类型转换(隐式装箱)

  1. isNaN();

隐示调用Number();然后将结果与NaN比较.所以:

isNaN(null);//false

isNaN(undefined);//ture

  1. ++、--、正负运算

隐示调用Number();然后再进行运算

  1. 加号

当加号两边有一个字符串的话,就会隐示调用String()将两边全部转换为字符串

  1. -、*、/、%

隐示调用Number()

  1. &&、||、!

判断之前,先用Boolean()转换成布尔值。再进行判断。

  1. <、>、<=、>=

有数字进行比较的会先转换成数字。纯字符串比较会比较ASCII码值。true比较时转化成1,false比较时会转化成0

  1. ==、!=

需要注意有三个特殊的值:

NaN == NaN; // false,NaN谁都不等于

undefined == null;//true

undefined和null即不等于true,也不等于false。

不发生类型转换的

  1. ===

类型也要相同才为true.但是NaN依然不等于NaN

  1. !==

image.png

null和undefined的区别

在if语句中,它们都会被自动转为false,相等运算符(==)甚至直接报告两者相等。

null是一个表示“空”的对象,转为数值时为0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN。

js判断数据类型的方法

typeofinstanceofconstructorObject.prototype.toString.call
优点使用简单能检测出引用类型基本能检测出所有类型(除null和undefined)可检测出所有类型
缺点只能检测出基本类型,除null,typeof(nulll)=object不能检测出基本类型,且不能跨iframeconstructor容易被修改,且不能跨iframeie6下,undefined和null均为object