引言:JavaScript有6种简单数据类型(也称为原始类型),分别是Undefined、Null、Boolean、Number、String、Symbol。还有一种复杂数据类型叫Object(对象)。Object是一种无序名值对的集合。因为在JavaScript中不能定义自己的数据类型,所有值都可以用上述7种数据类型之一来表示。
1 概述
JavaScript是一种弱类型语言,不用提前声明变量的数据类型就可以使用。在js程序运行过程中,变量的数据类型会被自动确定。
- 强类型语言:如:Java、C、C++、Python
- 弱类型语言:如:JavaScript、PHP
JavaScript中的数据类型分为两大类,基本数据类型 和复杂数据类型(也称为引用数据类型)
- 基本数据类型:Number(数字型)、String(字符串型)、Boolean(布尔型)、Null(空型)、Undefined(未定义型)、Symbol(符号)、BigInt(ES6新增)
- 复杂数据类型:Object(普通对象、数组对象、正则对象、日期对象、Math对象、函数对象)
2 基本数据类型
2.1 Number(数字型)
Number类型使用IEEE 754格式表示整数和浮点值(在某些语言中也叫双精度值)不同的数值类型相应地也有不同的数值字面量格式。
例如,整数可以用八进制(以8为基数)、十进制(以10为基数)或十六进制(以16为基数)字面量表示。
对于八进制字面量,第一个数字必须是0,然后是相应的八进制数字(数值0~7)。如果字面量中包含的数字超出了应有的范围,就会忽略前缀的0,后面的数字会被当成十进制数,如下所示:
js
let number1 = 065; // 八进制的53
let number2 = 098; // 无效的八进制数,会被当成98来处理
十进制字面量就是我们常用的表示方法,如下所示:
js
let number1 = 76; // 整数76
对于十六进制字面量,数值前缀是0x,然后是十六进制数字(0~9以及A~F)。十六进制数字中的字母大小写均可,如下所示:
js
let number1 = 0xa78; // 十六进制2680
let number2 = 0x1f; // 十六进制31
要定义浮点值,数值中必须包含小数点,并且小数点后面要有数字,例如:
js
let number1 = 3.4; // 小数
let number2 = .2; // 有效写法,代表0.2
let number3 = 5.; // 小数点后面没用数字,当成整数5处理
let number4 = 2.0; // 小数点后面是0,当成整数2处理
对于非常大或者非常小的数字,可以使用科学计数法来表示,默认情况下,js会将小数点后至少包含6个0的浮点值转换为科学计数法,例如:
js
let number1 = 2.345e7; // 等于23450000
let number2 = 0.00000000000000000005; // 等于5e-20
let number3 = 3e-5; // 等于0.00003
浮点值的精确度最高可达17位小数,但在算术计算中远不如整数精确,其最大与最小范围如下:
- 最大值:Number.MAX_VALUE,输出结果:1.7976931348623157e+308
- 最小值:Number.MIN_VALUE,输出结果:5e-324
因此,0.1加0.2得到的不是0.3,而是0.30000000000000004。由于这种微小的舍入错误,导致很难测试特定的浮点值。比如下面的例子:
数字型的3个特殊值:Infinity和- Infinity和NaN,举例:
- Infinity(无穷大) :如Number.MAX_VALUE*2
- -Infinity(无穷小) :如-Number.MAX_VALUE*2
- NaN(非数值): 如'abc' -- 100
- isNaN:用来判断一个变量是否为非数字的类型,返回值为true表示非数字,false表示是数字
2.2 String(字符串型)
字符串是指计算机中用于表示文本的一系列字符,在JavaScript中使用单引号或双引号来包裹字符串。
javascript
var str1 = '单引号字符串';
var str2 = "双引号字符串";
在单引号字符串中可以直接书写双引号,在双引号字符串中也可以直接书写单引号
javascript
var str1 = 'I am a "programmer"';
var str2 = "I'm a 'programmer'";
将以上语句输出,结果如下: 错误用法:
javascript
var str1 = 'I'm a programmer'; // 单引号错误用法
var str2 = "I'm a "programmer""; // 双引号错误用法
var str3 = 'I am a programmer"; // 单双引号混用
更多用法可以查看:JavaScript字符串概述
2.3 Boolean(布尔型)
布尔型通常用于逻辑判断,它有两个值:true和false,表示事物的"真"和"假",其中true的值为1,false的值为0。
javascript
console.log(true); // 输出结果:true
console.log(false); // 输出结果:false
console.log(true + 1); // 输出结果:2
console.log(false + 1); // 输出结果:1
2.4 undefined(未定义型)
如果一个变量声明后没有赋值 ,则变量的值就是undefined。Javascript会自动将声明但没有进行初始化的变量设为undifined。
javascript
var a;
console.log(a); // 输出结果:undefined
console.log(a + '_'); // 输出结果:undefined_(字符串型)
console.log(a + 1); // 输出结果:NaN
console.log(typeof a); // 输出结果:undefined
2.5 Null(空型)
null不能通过javascript来自动赋值,必须要我们自己手动来给某个变量赋值为null。
给一个变量赋一个null值,下面通过代码演示null值的使用。
javascript
var b = null;
console.log(b); // 输出结果:null
console.log(b + '_'); // 输出结果:null_(转化为字符串型)
console.log(b + 1); // 输出结果:1(null转换为0)
console.log(b + true); // 输出结果:1(null转换为0,true转换为1)
console.log(typeof b); // 输出结果:object
null 有属于自己的类型 Null,而不属于Object类型,typeof 之所以会判定为 Object 类型,是因为JavaScript 数据类型在底层都是以二进制的形式表示的,二进制的前三位为 0 会被 typeof 判断为对象类型,而 null 的二进制位恰好都是 0 ,因此,null 被误判断为 Object 类型。
2.6 Symbol
symbol 是ES6中新出现的一种基本数据类型,它是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用,表示独一无二的值。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
Symbol值通过Symbol()函数生成。
javascript
let name = Symbol("橘猫吃不胖");
console.log(s1); // Symbol(橘猫吃不胖)
console.log(s1.toString()) // "Symbol(橘猫吃不胖)"
console.log(s1.description); // "橘猫吃不胖"
console.log(typeof s1); // symbol
Symbol不能与其他类型的值进行运算,但是可以显式转为字符串,也可以转为布尔值,但是不能转为数值。
javascript
let s1 = Symbol("橘猫吃不胖");
console.log(s1 + 1); // TypeError: Cannot convert a Symbol value to a number
console.log("aaa" + s1); // TypeError: Cannot convert a Symbol value to a number
console.log(Boolean(s1)); // true
console.log(s1.toString()); // "Symbol(橘猫吃不胖)"
console.log(Number(s1)); // TypeError: Cannot convert a Symbol value to a number
2.7 BigInt
Number的局限性:JavaScript 中的 Number 是双精度浮点型,这意味着精度有限。Number.MAX_SAFE_INTEGER是安全范围内的最大值,为9007199254740991。最小安全值为 Number.MIN_SAFE_INTEGER,值为-9007199254740991,超出安全值的计算都会丧失精度。
BigInt 是一个新的原始类型,可以实现任意精度计算。创建 BigInt 类型的值也非常简单,只需要在数字后面加上 n 即可。也可以使用全局方法 BigInt(value) 转化,入参 value 为数字或数字字符串。
javascript
let a = BigInt(1234567890);
let b = 1234567890n;
console.log(a === b); // true
BigInt 与 Number 类型的值不严格相等:
javascript
console.log(123 === 123n); // false
console.log(123 == 123n); // true
3 两种数据类型存储方式(区别)
基本数据类型 是直接存储在栈 中的简单数据段,占据空间小、大小固定,属于被频繁使用的数据。栈是存储基本类型值和执行代码的空间。
引用数据类型 是存储在堆 内存中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。
4 数据类型检测
1、typeof:除了数组、对象、null会被判定为object,其他的判断都是正确的。
javascript
typeof 被判断的值 // 方式1
typeof(被判断的值) // 方式2
示例代码:
javascript
console.log(typeof 3); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object
typeof判断null为object类型的原因:JavaScript数据类型在底层都是以二进制表示的,二进制前3为是0会被判断为object类型,null的二进制都是0,因此会被判断为object类型。
2、instanceof:可以判断引用数据类型,原理是判断在被判断者的原型链中能不能找到该类型的原型。
javascript
a instanceof b
示例代码:
javascript
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
但是如果将数字型、字符串形和布尔型经过实例化后,就可以使用instanceof判断了:
javascript
new Number(1) instanceof Number // true
new String("str") instanceof String // true
new Boolean(true) instanceof Boolean // true
3、constructor
javascript
a.constructor === 类型
示例代码:
javascript
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
注意:如果创建一个实例对象改变它的原型,该方法判断数据类型就会失效。
javascript
function fun() { };
fun.prototype = new Array();
var f = new fun(); // 创建实例对象
console.log(f.constructor === Function); // false
console.log(f.constructor === Array); // true
4、Object.prototype.toString.call():使用Object对象的原型方法toString()来判断数据类型,这种方式所有的数据类型都可以被判断。
javascript
Object.prototype.toString.call(被判断的数据)
示例代码:
javascript
Object.prototype.toString.call(10) // [object Number]
Object.prototype.toString.call('90') // [object String]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call({}) // [object Object]
Object.prototype.toString.call([]) // [object Array]
Object.prototype.toString.call(function () { }) // [object Function]
Object.prototype.toString.call(this) // [object Window]
5 判断数组的方式
1、Array.isArray(被判断对象)
:返回true为数组,false不是数组
javascript
Array.isArray([1, 2, 3])
2、利用原型判断,true为数组,false不是数组
javascript
arr.__proto__ == Array.prototype
3、通过instanceof
判断,true为数组,false不是数组
javascript
obj instanceof Array
4、通过Object.prototype.toString.call()
判断
javascript
Object.prototype.toString.call(arr) // [object Array]
6 null和undefined的区别
undefined表示未定义的值,声明了但是不赋值,类型就是undefined。
null表示空值,必须手动为变量赋值为null,才可以成为null类型