JavaScript 共有两种数据类型分别为:值(基本)数据类型,引用数据类型。其中,
值数据类型有:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、符号(Symbol)。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。

注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。

JavaScript 拥有动态类型

JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型:

  1. var x; // x 为 undefined
  2. var x = 5; // 现在 x 为数字
  3. var x = "John"; // 现在 x 为字符串

字符串(String)

字符串是存储字符(比如 “Bill Gates”)的变量。 字符串可以是引号中的任意文本。您可以使用单引号或双引号:

  1. var name="Bill Gates";
  2. var name='Bill Gates';

您可以在字符串中使用引号,只要不匹配包围字符串的引号即可,下述三种写法都是正确的。

  1. var answer="It's alright";
  2. var answer="He is called 'Johnny'";
  3. var answer='He is called "Johnny"';

下述写法是错误的写法:

  1. var answer="He is called "Johnny"";
  2. var answer='He is called 'Johnny'';

String 类型的独特之处在于,它是唯一没有固定大小的原始类型。可以用字符串存储 0 或更多的 Unicode 字符,有 16 位整数表示。
字符串中每个字符都有特定的位置,首字符从位置 0 开始,第二个字符在位置 1,依此类推。这意味着字符串中的最后一个字符的位置一定是字符串的长度减 1:
数据类型 - 图1

数字(Number)

JavaScript 只有一种数字类型,Number 类型。这种类型既可以表示 32 位的整数,还可以表示 64 位的浮点数,即数字可以带小数点,也可以不带:

  1. var number1=34.00; //使用小数点来写
  2. var number2=34; //不使用小数点来写

八进制数和十六进制数

整数也可以被表示为八进制(以 8 为底)或十六进制(以 16 为底)的变量。八进制变量的首数字必须是 0,其后的数字可以是任何八进制数字(0-7),如下面的代码所示:

  1. var iNum = 070; //070 等于十进制的 56

要创建十六进制的变量,首位数字必须为 0,后面接字母 x,然后是任意的十六进制数字(0 到 9 和 A 到 F)。这些字母可以是大写的,也可以是小写的。例如:

  1. var iNum = 0x1f; //0x1f 等于十进制的 31
  2. var iNum = 0xAB; //0xAB 等于十进制的 171

提示:尽管所有整数都可以表示为八进制或十六进制的字面量,但所有数学运算返回的都是十进制结果。

浮点数

要定义浮点值,必须包括小数点和小数点后的一位数字(例如,用 1.0 而不是 1)。这被看作浮点数字面量。例如:

  1. var fNum = 5.0;

对于浮点变量的有趣之处在于,用它进行计算前,真正存储的是字符串。

科学计数法

极大或极小的数字可以通过科学(指数)计数法来书写,可以把一个数表示为数字(包括十进制数字)加 e(或 E),后面加乘以 10 的倍数。例如:

  1. var number1=123e5; // 12300000
  2. var number2=123e-5; // 0.00123

ECMAScript 默认把具有 6 个或 6 个以上前导 0 的浮点数转换成科学计数法

特殊的 Number 值

极值

几个特殊值也被定义为 Number 类型。前两个是 Number.MAX_VALUE 和 Number.MIN_VALUE,它们定义了 Number 值集合的外边界。所有 ECMAScript 数都必须在这两个值之间。不过计算生成的数值结果可以不落在这两个值之间。

当计算生成的数大于 Number.MAX_VALUE 时,它将被赋予值 Number.POSITIVE_INFINITY,意味着不再有数字值。同样,生成的数值小于 Number.MIN_VALUE 的计算也会被赋予值 Number.NEGATIVE_INFINITY,也意味着不再有数字值。如果计算返回的是无穷大值,那么生成的结果不能再用于其他计算。

事实上,有专门的值表示无穷大,(如你猜到的)即 Infinity。Number.POSITIVE_INFINITY 的值为 Infinity。Number.NEGATIVE_INFINITY 的值为 -Infinity。

由于无穷大数可以是正数也可以是负数,所以可用一个方法判断一个数是否是有穷的(而不是单独测试每个无穷数)。可以对任何数调用 isFinite() 方法,以确保该数不是无穷大。例如:

  1. var iResult = iNum * some_really_large_number;
  2. if (isFinite(iResult)) {
  3. alert("finite");
  4. }
  5. else {
  6. alert("infinite");
  7. }

NaN值

NaN,表示非数(Not a Number)。NaN 是个奇怪的特殊值。一般说来,这种情况发生在类型(String、Boolean 等)转换失败时。例如,要把单词 blue 转换成数值就会失败,因为没有与之等价的数值。与无穷大一样,NaN 也不能用于算术计算。NaN 的另一个奇特之处在于,它与自身不相等,这意味着下面的代码将返回 false:

  1. alert(NaN == NaN); //输出 "false"

出于这个原因,不推荐使用 NaN 值本身。函数 isNaN() 会做得相当好:

  1. alert(isNaN("blue")); //输出 "true"
  2. alert(isNaN("666")); //输出 "false"

布尔(Boolean)

布尔(逻辑)只能有两个值:true 或 false。布尔常用在条件判断中。
即使 false 不等于 0,0 也可以在必要时被转换成 false,这样在 Boolean 语句中使用两者都是安全的。

  1. var x=true;
  2. var y=false;

数组(Array)

数组用于存储具有相同类型的数据集合。数组下标是基于 0 的,所以第一个项目是 [0],第二个是 [1],以此类推。

  1. //先创建,再赋值
  2. var cars=new Array(); //var cars = [];这种方式也能创建一个数组
  3. cars[0]="Saab";
  4. cars[1]="Volvo";
  5. cars[2]="BMW";
  6. //创建一个数组,创建时初始化(condensed array)
  7. var cars=new Array("Saab","Volvo","BMW");
  8. //创建一个数组,创建时初始化(literal array),语法更简洁
  9. var cars=["Saab","Volvo","BMW"];

对象(Object)

对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。属性由逗号分隔:

  1. var person={firstName:"John", lastName:"Doe", id:5566};

上面例子中的对象 (person) 有三个属性:firstName、lastName 以及 id。
空格和折行无关紧要。声明可横跨多行:

  1. var person={
  2. firstName : "John",
  3. lastName : "Doe",
  4. id : 5566
  5. };

对象属性有两种寻址方式:

  1. name=person.lastName;
  2. name=person["lastName"];

未定义(Undefined)

Undefined 这个值表示变量不含有值。是所有没有赋值变量的默认值,自动赋值。
Undefined 类型只有一个值,即 undefined。当声明的变量未初始化时,该变量的默认值是 undefined。

  1. var carName;

测试该变量的值是否等于 undefined:

  1. alert(carName == undefined);//输出 "true"

这段代码将显示 “true”,说明这两个值确实相等。还可以用 typeof 运算符显示该变量的值是 undefined:

  1. alert(typeof oTemp); //输出 "undefined"

提示:值 undefined 并不同于未定义的值。但是,typeof 运算符并不真正区分这两种值。考虑下面的代码:

  1. var oTemp;
  2. alert(typeof oTemp); //输出 "undefined"
  3. alert(typeof oTemp2); //输出 "undefined"

前面的代码对两个变量输出的都是 “undefined”,即使只有变量 oTemp2 从未被声明过。如果对 oTemp2 使用除 typeof 之外的其他运算符的话,会引起错误,因为其他运算符只能用于已声明的变量上。
例如,下面的代码将引发错误:

  1. var oTemp;
  2. alert(oTemp2 == undefined);

当函数无明确返回值时,返回的也是值 “undefined”,如下所示:

  1. function testFunc() {
  2. }
  3. alert(testFunc() == undefined); //输出 "true"

空(Null)

主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。
Null 只有一个值 null,表示一个空对象引用。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。

  1. var carName=null;
  2. alert(carName == undefined); //输出 "true"

尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。

你可以设置为 null 来清空对象:

  1. var person = null; // 值为 null(空), 但类型为对象

你可以设置为 undefined 来清空对象:

  1. var person = undefined; // 值为 undefined, 类型为 undefined

undefined 和 null 的异同

共同点:都是原始类型,保存在栈中变量本地。
不同点:null 和 undefined 的值相等,但类型不等。undefined——表示变量声明过但并未赋过值;null——表示一个变量将来可能指向一个对象。

  1. typeof undefined // undefined
  2. typeof null // object
  3. null === undefined // false
  4. null == undefined // true

垃圾回收

null 和 undefined 是专门释放对象内存的一个程序。
(1)在底层,后台伴随当前程序同时运行;引擎会定时自动调用垃圾回收期;
(2)总有一个对象不再被任何变量引用时,才释放。

声明变量类型

当您声明新变量时,可以使用关键词 “new” 来声明其类型:

  1. var carName=new String;
  2. var x= new Number;
  3. var y= new Boolean;
  4. var cars= new Array;
  5. var person= new Object;

JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。

ECMAScript 原始值和引用值

在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。
原始值
存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
引用值
存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。

为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型。要实现这一点,解释程序则需尝试判断该值是否为 ECMAScript 的原始类型之一,即 Undefined、Null、Boolean、Number 和 String 型。由于这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 - 栈中。这样存储便于迅速查寻变量的值。

在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的。ECMAScript 打破了这一传统。

如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。如下图所示:
数据类型 - 图2

ECMAScript 原始类型

如前所述,ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。ECMA-262 把术语类型(type)定义为值的一个集合,每种原始类型定义了它包含的值的范围及其字面量表示形式。


ECMAScript 提供了 typeof 运算符来判断一个值是否在某种类型的范围内。可以用这种运算符判断一个值是否表示一种原始类型:如果它是原始类型,还可以判断它表示哪种原始类型。

typeof 运算符

typeof 运算符有一个参数,即要检查的变量或值。例如:

  1. var sTemp = "test string";
  2. alert (typeof sTemp); //输出 "string"
  3. alert (typeof 86); //输出 "number"

对变量或值调用 typeof 运算符将返回下列值之一:

  • undefined - 如果变量是 Undefined 类型的

  • boolean - 如果变量是 Boolean 类型的

  • number - 如果变量是 Number 类型的

  • string - 如果变量是 String 类型的

  • object - 如果变量是一种引用类型或 Null 类型的

注释:您也许会问,为什么 typeof 运算符对于 null 值会返回 “Object”。这实际上是 JavaScript 最初实现中的一个错误,然后被 ECMAScript 沿用了。现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。

由于数组也是一个对象,所以在判断数据类型是否是数组时,不能用 typeof (其返回值为 object),可以使用 isArray,instanceof 。

  1. //使用 isArray 方法
  2. var cars=new Array("Saab","Volvo","BMW");
  3. if (Array.isArray) { // 判断是否支持该方法
  4. if(Array.isArray(cars)) {
  5. document.write("该对象是一个数组。") ;
  6. }
  7. }
  8. //使用 instanceof 操作符
  9. var cars=["Saab","Volvo","BMW"];
  10. if (cars instanceof Array) {
  11. document.write("该对象是一个数组。") ;
  12. }