JavaScript 数据类型

编程语言中,能够表示并操作的值的类型称为数据类型,编程语言最基本的特性就是能够支持多种数据类型。


[ 编程领域中的数据类型 ]  在编程领域中,数据类型(datatype)用来将变量的值(value)进行分类,这样对变量的值进行数字、关系、逻辑等运算时就不会产生错误了。

2*2    // 符合逻辑        2 * 'tom'  // 不太符合逻辑

JavaScript 数据类型

ECMAScript 中有 5 种简单数据类型(又称为基本数据类型:Number、String、Boolean、Undefined、Null)和 1 种复杂数据类型 — Object。Object,本质上是由一组无序的名值对组成的。

ECMAScript 不支持任何创建自定义类型的机制,所有值始终都将是上述 6 种数据类型之一。实际上,由于 ECMAScript 数据类型具有动态性,因此,的确没有再定义其他数据类型的必要了。

简单来说,JavaScript 的数据类型分为两类:原始类型和对象类型(Object)。

  • 原始类型主要包括:Number、String、Boolean、Symbol(ES6新增)和空值(Null、Undefined)。
  • JS 中除原始类型之外的都是对象 Object,对象是键值对的集合,值可以是原始值,也可以是对象。

与此相对应,原始类型和对象类型的值,也分别被称为原始值和复杂值

  • 特性:原始值,不可更改;复杂值,是可变的,它们的值可以修改;
  • 存储方式:原始值,栈存储;复杂值,堆存储;
  • 访问方式:原始值,值访问;复杂值,引用访问;
  • 比较方式:原始值,值比较,复杂值,引用比较。复杂值只在引用相同的对象(即有相同的地址)时才相等。
  • 动态属性:复杂值,可以添加、改变和删除其属性和方法;但原始值不可添加属性和方法。

[1] 空值

  • Undefined 类型

Undefined 类型只有一个值:即特殊的 undefined,表示未定义或不存在。

# 在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined。
var abc;  // 这个变量未初始化
console.log(abc);    // undefined

    # 其他场景:已声明未赋值的变量 / 获取对象不存在的属性 / 无返回值的函数执行结果 / 函数参数没有传入 / void(expression)
      var obj = {}; console.log(obj.name); // undefined

# 对于尚未声明过的变量只能执行一项操作,使用typeof操作符检测其数据类型,严格模式下会出错。
// var abcd;  // 这个变量并没有声明
console.log(abcd);    // 报错,注意未声明和未赋值的区别

# 令人困惑的是,对未初始化的变量和未声明的变量执行 typeof 操作符都会返回 undefined 值,但实际意义不大。
typeof abc;  // undefined
typeof abcd;  // undefined
console.log(abc == abcd);  // true

  • Null 类型                                                  // 变量的值如果想为 null,必须手动设置

Null 类型是第二个只有一个值的数据类型,即 null。从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用 typeof 操作符检测 null 值时会返回“Object”的原因。

# 实际上,undefined 的值是派生自 null 值的,因此,ECMA-262 规定对它们的相等性测试要返回 true。

console.log(null == undefined);

尽管 null 和 undefined 有这样的关系,但它们的用途完全不同。无论什么情况下,都没有必要把一个变量的值显式的设置为 undefined,可同样的规则对于 null 却不适用。换句话来说,如果定义的变量准备在将来用于保存对象(还没有真正保存对象),就应该明确的让该变量保存为 null 值。

这样做,不仅可以体现 null 作为空对象指针的惯例,而且有助于进一步区分 null 和 undefined。


# 判断一个值是否为null类型的最佳方法是直接和 null 进行恒等比较。

console.log(document.getElementById('test'));  // null
 
// null是空对象指针,而[]是空数组,{}是空对象,三者不相同。
   console.log(typeof null);  // 'object

[2] Boolean 类型 ?↓

布尔是计算机科学中的逻辑数据类型,以发明布尔代数的数学家乔治 · 布尔为名,用来表示真或假、开或关等含义。

Boolean 类型是 ECMAScript 中使用最多的一种类型,该类型只有两个字面值:true 和 false,且区分大小写 。

// 在计算机内部存储,true 为 1,false 为 0

   var yes = true;
   var no = false;

// 布尔值与控制语句
   布尔值通常用于 if/else 控制语句,如果为 true,则执行 if 里面的逻辑,否则执行 else 里面的逻辑。
    if(status=='open'){
       console.log('The door is open');
    }else{
       console.log('The dooor is closed');
    }

// 布尔值:假值和真值
   任意值都可以转换为布尔值。一共有 6 个值(假值)会转换为 false,其他值(真值)都是 true。
   // 6 个假值:undefined    null    0    -0    NaN    ""

[3] Number 类型 ?↓( 对象 )

JavaScript 不区分整数和浮点数,所有的数值都用浮点数表示,采用 IEEE 754 标准定义的 64 位浮点格式。

[ 数值直接量和负值 ] JS 中的数值,称为数值直接量;在它前面添加负号(-,一元求反运算符),可以得到它的负值。

var num1 = 1;
var num2 = -2;

[ 进制表示 ] 进行算数运算时,二进制、八进制和十六进制表示的数值最终都将被转换成十进制数值。

  • 整数:范围是-253~253,可以用十进制、二进制、八进制、十六进制表示。
    • 0b11:二进制(binary)以 0b为前缀,之后的值由 0~1组成;
    • 067:八进制(octal)以 0 为前缀,之后的值由 0~7组成;
    • 0xAf:十六进制(hexadecimal)以 0x为前缀,之后的值由 0~9a~f10~15)组成;
所有二进制、八进制、十六进制中的字母不区分大小写,包括前缀中的字母;
以 0 为前缀的八进制,不推荐使用,在严格模式下会报语法错误。

  • 浮点数:数值中必须包含一个小数点,小数点后至少要有一位数字。如 3.14  .14

对于极大或极小的浮点数,可以使用科学计数法。如  3.14e10,即 3.14*(10∧10)

浮点数计算可能会有误差(使用 IEEE754 标准的浮点数计算的通病),如  0.1 + 0.2 = 0.30000000000000004


  • 特殊值:JS中,还有一些特殊值,主要来自:全局直接量、Number对象的属性、Math对象的属性等。
Infinity    NaN     Number.MAX_VALUE     Number.MIN_VALUE     Math.PI

[4] 字符串类型 String?↓

字符串用来表示文本,由零个或多个16位Unicode字符组成的字符序列;可以使用单引号(推荐)或双引号,但必须成对出现;索引从零开始,第一个是 0,第二个是 1,以此类推;长度是字符的个数。

'abc'    "123"
// ‘ab"c’  // 有效(双引号作为字符串内容)    “ab'c”  // 有效    “abc’  // 无效
 
// 推荐写法:单引号
  JS代码中,经常会出现HTML字符串。由于HTML标签中的属性值推荐的是双引号,所以,JS中字符串推荐使用单引号。
  var imgEl = '<img src = "logo.jpg" title="logo">';

[ 转义字符 ] 反斜杠后加一个字符表示转义字符,如 \表示换行符。

   ‘abc\'d’    'abc\nd'

// 常见的转义字符(如果斜杠后面的字符没有特殊含义,则忽略斜杠。如,\a等同于a。)
   \n    换行
   \\    斜杠
   \'    单引号,在用单引号表示的字符串中使用
   \"    双引号,在用双引号表示的字符串中使用
   \xnn    十六进制代码表示的一个字符(其中n为0~F)。如,\x41表示“A”。
   \unnnn  十六进制代码表示的unicode字符(其中n为0~F)。如\u03a3表示希腊字符∑。

[ 模板字符串 ] ES6 新增的写法,是允许嵌入表达式的字符串字面量。

// 模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。
// 它可以包含特定语法 ${expression} 的占位符。

   var abc = `abc`;    
   alert(abc);          // abc    
   alert(`${abc}def`);

[5] Symbol

ES6 新增的原始类型,可用作对象的非字符串属性,它是唯一且不可变的。

let uniqueName = Symbol();
let person= {};
 
person[uniqueName] = 'tom';
console.log(person[uniqueName]);    // =>John

[6] 对象 Object

ECMAScript 中的对象其实就是一组数据和功能的集合。

简单来说,除了原始类型的值外,其他的都是对象类型;对象是键值对的集合,值可以是原始值,也可以是对象。

var person = {
    name:'tom',
    age:25
}
 
// 重要的特殊对象:函数Function    数组Array    日期Date    正则RegExp    错误Error    全局Global

[ 数据类型的识别与转换 ?↓ ] 鉴于 ECMAScript 是松散类型的,因此,需要有一种手段来检测给定变量的数据类型 — typeof 就是负责提供这方面信息的操作符。需要说明的是,typeof 的结果是一个小写的字符串。

typeof 是一个操作符而不是函数,因此其后面的(),尽管可以使用,但不是必需的。

typeof 操作符的操作数可以是变量(message),也可以是数值字面量。

var abc;    // undefined
var abc = true;    // boolean
var abc = 123;    // number
var abc = 'abc';    // string
var abc = function (){};    // function
var abc = {};    // [],null    // object
var abc = Symbol();    // symbol
 
alert(typeof abc);
// alert(typeof(abc))