JavaScript数据类型概述

引言

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格式表示整数和浮点值(在某些语言中也叫双精度值),不同的数值类型相应地也有不同的数值字面量格式。

1.整数

整数可以用八进制(以8为基数)、十进制(以10为基数)或十六进制(以16为基数)字面量表示。

对于八进制字面量,第一个数字必须是0,然后是相应的八进制数字(数值0~7)。如果字面量中包含的数字超出了应有的范围,就会忽略前缀的0,后面的数字会被当成十进制数,如下所示:

let number1 = 065; // 八进制的53
let number2 = 098; // 无效的八进制数,会被当成98来处理

十进制字面量就是我们常用的表示方法,如下所示:

let number1 = 76; // 整数76

对于十六进制字面量,数值前缀是0x,然后是十六进制数字(0~9以及A~F)。十六进制数字中的字母大小写均可,如下所示:

let number1 = 0xa78; // 十六进制2680
let number2 = 0x1f; // 十六进制31

常见的进制

  • 八进制数:在数字开头加上0,八进制数由0~7组成,逢8进位
  • 十进制数:是组成以10为基础的数字系统,有0~9组成,逢10进位
  • 十六进制数:在数字开头加上0x,十六进制数由0 ~ 9,a ~ f组成
2.浮点数

要定义浮点值,数值中必须包含小数点,并且小数点后面要有数字,例如:

let number1 = 3.4; // 小数
let number2 = .2; // 有效写法,代表0.2
let number3 = 5.; // 小数点后面没用数字,当成整数5处理
let number4 = 2.0; // 小数点后面是0,当成整数2处理

对于非常大或者非常小的数字,可以使用科学计数法来表示,默认情况下,js会将小数点后至少包含6个0的浮点值转换为科学计数法,例如:

let number1 = 2.345e7; // 等于23450000
let number2 = 0.00000000000000000005; // 等于5e-20
let number3 = 3e-5; // 等于0.00003

浮点值的精确度最高可达17位小数,但在计算中不如整数精确,例如0.1加0.2得到的不是0.3,而是0.30000000000000004。

3.范围

ECMAScript可以表示的最大值与最小值分别是:

  • 最大值:Number.MAX_VALUE,输出结果:1.7976931348623157e+308
  • 最小值:Number.MIN_VALUE,输出结果:5e-324

如果计算得到的数值超过了JavaScript表示的范围,那么表示为Infinity(正无穷大)和-Infinity(负无穷大)。

判断这个值是不是无穷大,可以使用isFinite()函数,如下所示:

let result = Number.MAX_VALUE + Number.MAX_VALUE;
isFinite(result); // false
4.NaN

NaN意思是不是数值,它用来表示数学运算没有成功的值,而且任何涉及NaN的操作会始终返回NaN。例如:

5 / 0 // NaN
NaN - 1 // NaN

并且,NaN是一个自反的值,即:

NaN === NaN // false
NaN == NaN // false
NaN !== NaN // true

ECMAScript提供了isNaN()函数,该函数可以判断这个参数是否“不是数值”。把一个值传给 isNaN()后,该函数会把它转换为数值,可以转化成数值的为true,不能转化为数值的为false,例如:

isNaN(NaN) // true
isNaN(40000) // false
isNaN("jumaochibupang") // true,不可以转化为数值
isNaN("300") // false,可以转化为数值300
isNaN(false) // false,可以转化为数值0

2.2 String(字符串型)

字符串是指计算机中用于表示文本的一系列字符,在JavaScript中使用单引号''或双引号""或反引号``来包裹字符串。

var str1 = '单引号字符串';
var str2 = "双引号字符串";
var str3 = `反引号字符串`;

在单引号字符串中可以直接书写双引号,在双引号字符串中也可以直接书写单引号

var str1 = 'I am a "programmer"';
var str2 = "I'm a 'programmer'";

将以上语句输出,结果如下:
在这里插入图片描述
以某种引号作为字符串开头,必须仍然以该种引号作为字符串结尾,错误用法:

var str1 = 'I'm a programmer'; // 单引号错误用法
var str2 = "I'm a "programmer""; // 双引号错误用法
var str3 = 'I am a programmer";	// 单双引号混用

更多用法可以查看:JavaScript字符串概述

2.3 Boolean(布尔型)

布尔型通常用于逻辑判断,它有两个值:truefalse,表示事物的“真”和“假”,其中true的值为1,false的值为0。

console.log(true); // 输出结果:true
console.log(false);	// 输出结果:false
console.log(true + 1); // 输出结果:2
console.log(false + 1);	// 输出结果:1

2.4 undefined(未定义型)

如果一个变量声明后没有赋值,则变量的值就是undefined。JS会自动将声明但没有进行初始化的变量设为undifined

var a;

console.log(a);	// 输出结果:undefined
console.log(a + '_'); // 输出结果:undefined_(字符串型)
console.log(a + 1);	// 输出结果:NaN
console.log(typeof a); // 输出结果:undefined

2.5 Null(空型)

null不能通过JS来自动赋值,必须要我们自己手动来给某个变量赋值为null

给一个变量赋一个null值,下面通过代码演示null值的使用。

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类型,是因为JS数据类型在底层都是以二进制的形式表示的,二进制的前三位为0会被typeof判断为对象类型,而null的二进制位恰好都是0,因此,null被误判断为Object类型。

2.6 Symbol(符号)

Symbol是ES6中新出现的一种基本数据类型,它是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用,表示独一无二的值。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol值通过Symbol()函数初始化,例如:

let name = Symbol();
typeof name; // symbol

调用Symbol()函数时,可以传入一个字符串参数作为对符号的描述(description),但是这个字符串参数与符号标识无关

let name = Symbol("橘猫吃不胖");

s1; // Symbol(橘猫吃不胖)
s1.description; // "橘猫吃不胖"

Symbol不能与其他类型的值进行运算,但是可以显式转为字符串,也可以转为布尔值,但是不能转为数值。

let s1 = Symbol("橘猫吃不胖");

s1.toString() // "Symbol(橘猫吃不胖)"
Boolean(s1); // true
s1 + 1; // TypeError: Cannot convert a Symbol value to a number
"aaa" + s1; // TypeError: Cannot convert a Symbol value to a number
Number(s1); // TypeError: Cannot convert a Symbol value to a number

2.6.1 Symbol的一些方法

1.Symbol.for()和Symbol.keyFor()

如果想在不同的代码中共享同一个符号值的话,可以使用Symbol.for()方法注册符号。Symbol.for()方法接收一个字符串作为参数,任何值传给Symbol.for()都会被转化成字符串,作为目标符号的标识符与描述信息。

let uid = Symbol.for("uid");
let obj1 = {};
obj1[uid] = "1111111111";

let cid = Symbol.for("uid");
let obj2 = {};
obj2[cid] = "2222222222";

uid === cid // true

Symbol.for()对每个字符串键都执行幂等操作,它会首先搜索全局符号注册表,看看是否存在键为uid的符号值,如果存在,则会返回这个已经存在的符号值,如果不存在,则会创建一个新的符号值并返回,并将其记录到全局符号注册表中

如果要查询全局符号注册表,可以使用Symbol.keyFor()函数,这个方法接收符号作为参数,最后返回该全局符号对应的字
符串键。如果查询的不是全局符号,则返回undefined

let uid = Symbol.for("uid");
let s1 = Symbol();
Symbol.keyFor(uid); // uid
Symbol.keyFor(s1); // undefined 

2.7 BigInt

Number的局限性:JavaScript 中的 Number 是双精度浮点型,这意味着精度有限。Number.MAX_SAFE_INTEGER是安全范围内的最大值,为9007199254740991。最小安全值为 Number.MIN_SAFE_INTEGER,值为-9007199254740991,超出安全值的计算都会丧失精度。

BigInt 是一个新的原始类型,可以实现任意精度计算。创建 BigInt 类型的值也非常简单,只需要在数字后面加上 n 即可。也可以使用全局方法 BigInt(value) 转化,入参 value 为数字或数字字符串。

let a = BigInt(1234567890);
let b = 1234567890n;
console.log(a === b); // true

BigInt 与 Number 类型的值不严格相等:

console.log(123 === 123n); // false
console.log(123 == 123n); // true

3 复杂数据类型Object

Object对象其实就是一组数据和功能的集合,对象可以通过new操作符后跟对象类型的名称来创建。Object类型也是派生其他对象的基类,其所有的属性和方法在派生的对象上同样存在。

每个Object实例都有如下属性和方法:

  • constructor:用于创建当前对象的函数
  • hasOwnProperty(propertyName):用于判断当前对象实例上是否存在给定的属性,要检查的属性名必须是字符串或符号
  • isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型
  • propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用for-in语句枚举,属性名必须是字符串
  • toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境
  • toString():返回对象的字符串表示
  • valueOf():返回对象对应的字符串、数值或布尔值表示

4 数据类型转换

4.1 显式类型转换

4.1.1 转换为Number类型

1.Number()

Number()可用于转化任何数据类型,会基于如下规则执行转换:

// (1)参数为布尔值,true为1,false为0
Number(true); // 1
Number(false); // 0
// (2)参数为数值,直接返回当前数值
Number(00000999); // 999,忽略0
Number(99.99); // 99.99
Number(0x68); // 104
// (3)参数为null,返回0
Number(null); // 0
// (4)参数为undefined,返回NaN
Number(undefined); // NaN
// (5)参数为字符串:①数值字符串,返回该数值;②参数为空字符串,返回0;③参数为其他字符串,返回NaN
Number("00023.78"); // 23.78
Number(""); // 0
Number("ju mao chi bu pang"); // NaN
2.parseInt()

parseInt()函数主要用在字符串转化为整数,更专注于字符串是否包含数值模式,它接受2个参数,第一个参数为字符串,第二个参数为2-36之间的整数,表示转换进制,如果不传第二个参数,默认按照十进制进行转换,其转换规则如下:

// (1)如果字符串前面有空格,空格会被忽略,从第一个非空格字符开始转换
parseInt("  82   "); // 82
// (2)如果第一个非空格字符不是数字、+或者-,立即返回NaN,空字符串也会返回NaN
parseInt(" jumao666"); // NaN
parseInt(""); // NaN
// (3)如果第一个字符是数值字符、加号或减号,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符
parseInt("-8989"); // -8989
parseInt("-8989ssssss111"); // -8989,ssssss111会被忽略
parseInt("-8989.8989"); // -8989,小数点会被忽略
// (4)如果只传1个参数,该函数可以识别不同的整数格式转化为10进制,例如8进制转10进制、16进制转10进制等,如果传入第2个参数,则会解析为指定进制数
parseInt("0xAF"); // 175,10进制175
parseInt("AF", 16); // 175,指定进制数可以省略前缀
parseInt("100", 2); // 4,100按照2进制解析为4
parseInt("100", 8); // 64,100按照8进制解析为64
parseInt("100", 10); // 4,100按照10进制解析为100
parseInt("100", 16); // 4,100按照16进制解析为256
3.parseFloat()

parseFloat()函数跟parseInt()函数类似,都是从位置0开始检测每个字符,解析到字符串末尾或者解析到一个无效的浮点数值字符为止。

它的不同之处在于,第一次出现的小数点是有效的,但第二次出现的小数点就无效了,并且始终忽略字符串开头的0,其转换规则如下:

parseFloat("1234jumaochibupang"); // 1234,按整数解析
parseFloat("0xA"); // 0,十六进制始终返回0,只能解析十进制数字
parseFloat("22.5"); // 22.5
parseFloat("22.34.5"); // 22.34,第二次出现的小数点无效
parseFloat("0908.5"); // 908.5,忽略字符串开头的0
parseFloat("3.125e7"); // 31250000

4.1.2 转换为String类型

1.toString()

除了nullundefined值,几乎所有值都有toString()方法,这个方法会返回当前值的字符串等价物。

let age = 11; 
let ageAsString = age.toString(); // 字符串"11" 
let found = true; 
let foundAsString = found.toString(); // 字符串"true"

Number类型调用这个方法时,toString()可以接收1个底数作为参数,作为数字转换的进制数,例如:

let num = 10;
num.toString(); // "10",默认情况下返回10进制字符串
num.toString(2); // "1010",输出10的2进制字符串
num.toString(8); // "12",输出10的8进制字符串
num.toString(16); // "a",输出10的16进制字符串
2.String()

String()可以转化任何数据类型,它遵循以下转化规则:

  • 如果值有toString()方法,则调用该方法;
  • 如果值为nullundefined,则返回"null""undefined"

示例代码如下:

String(10); // "10"
String(true); // "true"
String(null); // "null"
String(undefined); // "undefined"

4.1.3 转换为Boolean类型

要将一个其他类型的值转换为布尔值,可以调用特定的Boolean()转型函数:

Boolean("jumaochibupang"); 

Boolean()转型函数可以在任意类型的数据上调用,而且始终返回一个布尔值,不同类型与布尔值之间的转换规则如下:

Boolean("aaaaa"); // true,非空字符串转化为true
Boolean(""); // false,空字符串转化为false
Boolean(1223); // true,非0数值转化为true
Boolean(0); // 0转化为false
Boolean([]); // true,任意对象转化为true
Boolean(null); // false,null转化为false
Boolean(undefined); // false,undefined转化为false

4.2 隐式类型转换

4.2.1 转换为Number类型

4.2.2 转换为String类型

4.2.3 转换为Boolean类型

if等流控制语句中,会自动执行其他类型值到布尔值的转换,例如:

let message = "Hello world!"; 
if (message) { 
 console.log("橘猫吃不胖"); 
} 

在这个例子中,log会输出字符串"橘猫吃不胖",因为字符串message会被自动转换为等价的布尔值 true

3 两种数据类型存储方式(区别)

基本数据类型是直接存储在中的简单数据段,占据空间小、大小固定,属于被频繁使用的数据。栈是存储基本类型值和执行代码的空间

引用数据类型是存储在内存中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。

4 数据类型检测

1、typeof:除了数组、对象、null会被判定为object,其他的判断都是正确的。

typeof 被判断的值 // 方式1
typeof(被判断的值) // 方式2

示例代码:

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:可以判断引用数据类型,原理是判断在被判断者的原型链中能不能找到该类型的原型。

a instanceof b

示例代码:

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判断了:

new Number(1) instanceof Number               // true
new String("str") instanceof String           // true
new Boolean(true) instanceof Boolean          // true

3、constructor

a.constructor === 类型

示例代码:

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

注意:如果创建一个实例对象改变它的原型,该方法判断数据类型就会失效。

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()来判断数据类型,这种方式所有的数据类型都可以被判断。

Object.prototype.toString.call(被判断的数据)

示例代码:

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不是数组

Array.isArray([1, 2, 3])

2、利用原型判断,true为数组,false不是数组

arr.__proto__ == Array.prototype

3、通过instanceof判断,true为数组,false不是数组

obj instanceof Array

4、通过Object.prototype.toString.call()判断

Object.prototype.toString.call(arr) // [object Array]

6 null和undefined的区别

undefined表示未定义的值,声明了但是不赋值,类型就是undefined。

null表示空值,必须手动为变量赋值为null,才可以成为null类型

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值