JavaScript 数据类型


个人主页:学习前端的小z
个人专栏:JavaScript 精粹
本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论!


在这里插入图片描述


✍JavaScript数据类型

JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有七种。

  • 数值(number):整数和小数(比如13.14
  • 字符串(string):文本(比如'Hello World')。
  • 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
  • undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
  • null:表示空值,即此处的值为空 。
  • 对象(object):各种值组成的集合。
  • symbol (symbol ) : 唯一标识符
通常,数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值。

🍎1 类型分类

传统分类通过存储位置 把数据类型分为 基础类型 和 引用类型

基础类型 存储在 栈内存 中
Undefined、Null、Boolean、Number、String和symbol

在这里插入图片描述

🍁1.1 Number 类型

  • 数值字面量:数值的固定值的表示法

    110 1024 60.5

  • 进制

十进制
	var num = 9;
	进行算数计算时,八进制和十六进制表示的数值最终都将被转换成十进制数值。
十六进制
	var num = 0xA;
	数字序列范围:0~9以及A~F
八进制
    var num1 = 07;   // 对应十进制的7
    var num2 = 019;  // 对应十进制的19
    var num3 = 08;   // 对应十进制的8
    数字序列范围:0~7
    如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析
  • 浮点数

    • 浮点数的精度问题
浮点数
	var n = 5e-324;   // 科学计数法  5乘以10的-324次方  
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
   var result = 0.1 + 0.2;    // 结果不是 0.3,而是:0.30000000000000004
   console.log(0.07 * 100);
   不要判断两个浮点数是否相等
  • 数值范围
最小值:Number.MIN_VALUE,这个值为: 5e-324
最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
无穷大:Infinity
无穷小:-Infinity
  • 数值判断

    • NaN:not a number 表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。
      • NaN 与任何值都不相等,包括他本身
    • isNaN: is not a number
    • NaN进行任何数学运算 结果也是 NaN

🍁1.2 数值精度问题

根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。

  • 第1位:符号位,0表示正数,1表示负数
  • 第2位到第12位(共11位):指数部分
  • 第13位到第64位(共52位):小数部分(即有效数字)

符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

指数部分一共有11个二进制位,因此大小范围就是0到2047。IEEE 754 规定,如果指数部分的值在0到2047之间(不含两个端点),那么有效数字的第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字这时总是1.xx...xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript 提供的有效数字最长为53个二进制位。

(-1)^符号位 * 1.xx...xx * 2^指数部分

上面公式是正常情况下(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。

精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-253到253,都可以精确表示。

🍁1.3 数值范围

根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。

如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity

🍁1.4 String类型

‘joker’ “kyogre”

  • 字符串字面量

    ‘海牙老师 真的帅’

  • 转义符

    在这里插入图片描述

  • 字符串长度 (只读)

    length属性用来获取字符串的长度

    var str = '海牙 Hello World';
    console.log(str.length);
    
  • 字符串拼接

    字符串拼接使用 + 连接

    console.log(11 + 11);
    console.log('hello' + ' world');
    console.log('100' + '100');
    console.log('11' + 32);
    console.log('male:' + true);
    
    1. 两边只要有一个是字符串,那么+就是字符串拼接功能
    2. 两边如果都是数字,那么就是算术功能。
  • 字符串换行

    var longString = '第一行 '
      + '第二行 '
      + '第三行 '
      + '文本内容';
      
      
    var longString = '第一行 \
    第二行 \
    第三行 \
    文本内容';
    
    longString
    
  • 按位取值(只读)

    var str = 'hello world!';
    console.log(str[1]); //e
    str[1] = 'x'; //无法改写 
    

🍁1.5 Boolean类型

布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。

  • Boolean字面量: true和false,区分大小写
  • 计算机内部存储:true为1,false为0

🍁1.6 Undefined和Null

nullundefined都可以表示“没有”,含义非常相似。将一个变量赋值为undefinednull,老实说,语法效果几乎没区别。

  1. undefined表示一个声明了没有赋值的变量,变量只声明的时候值默认是undefined
  2. null表示一个空,变量的值如果想为null,必须手动设置

在javascript设计初期 null就像在 Java 里一样,被当成一个对象。初像 Java 一样,只设置了null表示"无"。根据 C 语言的传统,null可以自动转为0。 但是javascript并没有完整的ERROR机制 null可以转换为0 对于javascript这种弱类型的语言来说 不利于发现bug 所以设计了 undefined 变量默认值也就成为了 undefined

所以在学习javascript的过程中 不能用java等编程语言的null来理解javascript中的null

在javascript中 null是 对象的延伸 是一个 ‘空’ 对象。var str = '';'' 不能用null判断 他是有值的 内存中分配了空间来存储 '' 一个空字符串值。null在javascript中常见于释放内存空间 var str = null;

🍎2 类型判断

JavaScript 有三种方法,可以确定一个值到底是什么类型。

  • typeof运算符
  • instanceof运算符
  • Object.prototype.toString方法

🍁2.1 typeof

数值、字符串、布尔值分别返回numberstringboolean, undefined返回undefined null返回object

typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
typeof undefined //"undefined"
typeof null // "object"

typeof 针对未声明的变量

if (typeof v === "undefined" ) {
   console.log("变量 v 不存在")
}

🍁2.2 isNaN

isNaN方法可以用来判断一个值是否为NaN

isNaN(NaN) // true
isNaN(123) // false

但是,isNaN只对数值有效,如果传入其他值,会被先转成数值。比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。也就是说,isNaNtrue的值,有可能不是NaN,而是一个字符串。

isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true

出于同样的原因,对于对象和数组,isNaN也返回true

isNaN({}) // true
// 等同于
isNaN(Number({})) // true

isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true

但是,对于空数组和只有一个数值成员的数组,isNaN返回false

isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false

上面代码之所以返回false,原因是这些数组能被Number函数转成数值

因此,使用isNaN之前,最好判断一下数据类型。

function myIsNaN(value) {
  return typeof value === 'number' && isNaN(value);
}

判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。

function myIsNaN(value) {
  return value !== value;
}

🍁2.3 isFinite

isFinite方法返回一个布尔值,表示某个值是否为正常的数值。

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true

除了Infinity-InfinityNaNundefined这几个值会返回falseisFinite对于其他的数值都会返回true

🍎3 操作符

运算符 operator

5 + 6

表达式 组成 操作数和操作符,会有一个结果

🍁3.1 算术运算符

  • 加法运算符x + y
  • 减法运算符x - y
  • 乘法运算符x * y
  • 除法运算符x / y
  • 指数运算符x ** y
  • 余数运算符x % y
  • 自增运算符++x 或者 x++
  • 自减运算符--x 或者 x--
  • 数值运算符+x
  • 负数值运算符-x

🍁3.2 一元运算符

一元运算符:只有一个操作数的运算符

1 + 2 两个操作数的运算符 二元运算符

++ 自身加1

– 自身减1

  • 前置++

    var num1 = 5;
    ++ num1; 
    
    var num2 = 6;
    console.log(num1 + ++ num2);
    
  • 后置++

    var num1 = 5;
    num1 ++;    
    var num2 = 6 
    console.log(num1 + num2 ++);
    
  • 猜猜看

    var a = 1; var b = ++a + ++a; console.log(b);    
    var a = 1; var b = a++ + ++a; console.log(b);    
    var a = 1; var b = a++ + a++; console.log(b);    
    var a = 1; var b = ++a + a++; console.log(b);  
    

    总结
    前置++:先加1,后参与运算
    后置++:先参与运算,后加1
    上面两个理解后,下面两个自通
    前置-- :先减1,后参与运算
    后置-- :先参与运算,后减1

🍁3.3 逻辑运算符(布尔运算符)

&& 与 两个操作数同时为true,结果为true,否则都是false
|| 或 两个操作数有一个为true,结果为true,否则为false
!  非  取反

🍁3.4 关系运算符(比较运算符)

<  >  >=  <= == != === !==
=====的区别:==只进行值得比较,===类型和值同时相等,则相等

var result = '55' == 55;  	// true
var result = '55' === 55; 	// false 值相等,类型不相等
var result = 55 === 55; 	// true

🍁3.5 赋值运算符

= += -= *= /= %=

例如:
var num = 0;
num += 5;	//相当于  num = num + 5;

🍁3.6 二进制运算符 (了解)

javascript 支持二进制运算 ~ | & >> << >>> ^

异或运算 ^ 
异或运算(^)在两个二进制位不同时返回1,相同时返回0。

一般可以用来做开关或者倒值
var a = 33;
var b = 66;

a ^= b, b ^= a, a ^= b;

a // 66
b // 33
否运算符 ~

一般用于 双否 取整
~~ 13.33    // 13

🍁3.7 运算符的优先级

优先级从高到底
	1. ()  优先级最高
	2. 一元运算符  ++   --   !
	3. 算数运算符  先*  /  %   后 +   -
	4. 关系运算符  >   >=   <   <=
	5. 相等运算符   ==   !=    ===    !==
	6. 逻辑运算符 先&&   后||
	7. 赋值运算符
	8. 默认从左至右 除了 赋值运算 = 三目运算 ?: 指数运算 **
// 练习1:
4 >= 6 || '山海' != '琨' && !(12 * 2 == 144) && true
// 练习2:
var num = 10;
5 == num / 2 && (2 + 2 * num).toString() === '22'

注: Unicode 码表查询地址:https://www.ltool.net/characters-to-unicode-charts-in-simplified-chinese.php

🍎4 数据类型转换

chrome浏览器中 不同类型的值 打印颜色不同

字符串的颜色是黑色的,数值类型是蓝色的,布尔类型也是蓝色的,undefined和null是灰色的

🍁4.1 转换成字符串类型

  • toString()

    var num = 5;
    console.log(num.toString());
    
  • String()

    String()函数存在的意义:有些值没有toString(),这个时候可以使用String()。比如:undefined和null
    
  • 拼接字符串方式

    num + “”,当 + 两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型转换成字符串再进行字符串拼接,返回字符串

🍁4.2 转换成数值类型

  • Number(Obj)

    Number()可以把任意值转换成数值,如果要转换的字符串中有一个不是数值的字符,返回NaN
    
  • parseInt(string,radix)

    var num1 = parseInt("12.3abc");  // 返回12,如果第一个字符是数字会解析知道遇到非数字结束
    var num2 = parseInt("abc123");   // 返回NaN,如果第一个字符不是数字或者符号就返回NaN
    
  • parseFloat(string)

    parseFloat()把字符串转换成浮点数
    parseFloat()和parseInt非常相似,不同之处在与
    	parseFloat会解析第一个. 遇到第二个.或者非数字结束
    	如果解析的内容里只有整数,解析成整数
    
  • +,-0等运算

    var str = '500';
    console.log(+str);		// 取正
    console.log(-str);		// 取负
    console.log(str - 0);
    

🍁4.3 转换成布尔类型

  • Boolean()

  • !!

    ''(空字符串) null undefined NaN 0 会转换成false 其它都会转换成true

🍎5 隐式转换

🍁5.1 递增递减运算符(前置、后置)

  1. 如果包含的是有效数字字符串或者是有效浮点数字符串,则会将字符串转换(Number())为数值,再进行加减操作,返回值的类型是:number类型。

  2. 如果不包含有效数字字符串,则会将字符串的值转换为NaN,返回值的类型是:number类型。

  3. 如果是boolean类型,则先会把true或者false转换为1或者0,再进行加减操作,返回值的类型是:number类型。

  4. 如果是null类型,则先会把null转换为0,在进行加减操作,返回值的类型是:number类型。

  5. 如果是undefined,则先会把undefined转换为NaN,再进行加减操作,返回值的类型是:number类型。

  6. 如果是对象,则先会通过对象的valueOf()方法,进行转换,如果返回的是NaN,调用toString()方法,在进行前面的操作,返回值的类型是:number类型。(注:空数组[]会返回0,在进行加减操作,空对象则会返回NaN)。

🍁5.2 逻辑操作符中的隐式转换规律

注:只有undefined、null、NaN、0、空字符串会被转换为false,其余都为true

逻辑操作符一般用于语句判断中。通过判断结果返回的值进行后面的语句操作。

  1. 逻辑非(!)操作符:首先会通过Boolean()函数将其操作值转换为布尔值,然后求反。
  2. 逻辑与(&&)操作符:如果第一个值经过Boolean()函数转换后为true,则返回第二个操作值,否则返回第一个操作值。如果有一个操作值为null这返回null,如果有一个操作值为undefined,则返回undefined,如果有一个值为NaN,则返回NaN。
  3. 逻辑或(||)操作符:如果第一个值经过Boolean()函数转换为false,则返回第二个操作值,否则返回第一个操作值。
    (注:逻辑操作符的运算为短路逻辑运算:前一个条件已经能够得出结果后续条件不再执行!)

🍁5.3 关系操作符的隐式转换规律

(关系操作符的操作值也可以是任意类型):

  1. 如果两个操作值都是数值,则直接比较大小。
  2. 如果两个操作值都是字符串,则字符串进行其Unicode编码进行比较。
  3. 如果一个操作值是数值,则另一个值转换为数值进行比较。
  4. 如果一个操作值是对象,则调用对象的valueOf()和toString()方法,然后再进行上述比较。
  5. 如果一个操作值是布尔值,则将布尔值转换为数值再进行比较。
    (注:NaN和任何值都不相等,包括自己,同时它与任何类型比较都会返回false。)

🍁5.4 相等操作符== 和 ===的隐式转换规律:

  1. 布尔值、字符串和数值进行比较,会先将其转换为数值再进行比较。
  2. null和undefined比较是相等的,但不是全等的。
  3. NaN与任何值都不相等,都会返回false。

🍁5.5 布尔类型的隐式转换

流程控制语句会把后面的值隐式转换成布尔类型

转换为true   非空字符串  非0数字  true 任何对象
转换成false  空字符串  0  false  null  undefined NaN
// 结果是什么?
var a = !!'123';
🌷5.5.1 转换不同的数据类型时,相等和不相等操作符遵循下列基本规则:
  • 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为 0,而true 转换为 1;
  • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
  • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类型值按照前面的规则进行比较;

这两个操作符在进行比较时则要遵循下列规则。

  • null 和 undefined 是相等的。

  • 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。

  • 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。 重要提示:即使两个操作数都是 NaN,相等操作符也返回 false;因为按照规则, NaN 不等于 NaN。

  • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,
    则相等操作符返回 true;否则,返回 false。

    表达式
    null==undefined true
    “NaN”==NaN false
    5==NaN false
    NaN==NaN false
    false==0 true
    true==1 true
    true==2 false
    undefined==0 false
    null==0 false

null == undefined 会返回 true,因为它们是类似的值;但 null === undefined 会返回 false,因为它们是不同类型的值。

🍁5.6 === 转换

字符串操作环境 数字运算环境 逻辑运算环境 对象操作环境
undefined “undefined” NaN false Error
null “null” 0 false Error
非空字符串 不转换 字符串对应的数字值 True
空字符串 不转换 0 false String
0 “0” 不转换 false Number
NaN “NaN” 不转换 false Number
Infinity “Infinity” 不转换 true Number
Number.POSITIVE_INFINITY “Infinity” 不转换 true Number
Number.NEGATIVE_INFINITY “-Infinity” 不转换 true Number
Number.MAX_VALUE “1.7976931348623157e+308” 不转换 true Number
Number.MIN_VALUE “5e-324” 不转换 true Number
其他所有数字 “数字的字符串值” 不转换 true Number
true “true” 1 不转换 Boolean
false “false” 0 不转换 Boolean
对象 toString() value()或toString()或NaN true 不转换

测试:

1 + true;
1 + 'true';
1 + undefined;
1 + null;
NaN == NaN;
undefined == null;
null !== undefined;
2 + '5' - 3;
6 > '3' == 3;
undefined == '0';
null == 0;
null >= 0;
parseInt('13.33') === ~~'13.33';
false - 1 <= '0';
'Value is ' + (val != '0') ? 'define' : 'undefine';

关于 null 在关系运算和相等运算中的坑:

null > 0   // null 尝试转型为number , 则为0 . 所以结果为 false, 
null >= 0  // null 尝试转为number ,则为0 , 结果为 true. 
null == 0  // null在设计上,在此处不尝试转型. 所以 结果为false. 

参考 : http://bclary.com/log/2004/11/07/#a-11.9.3

  1. 关系运算符 和 相等运算符 并不是一个类别的.
  2. 关系运算符,在设计上,总是需要运算元尝试转为一个number . 而相等运算符在设计上,则没有这方面的考虑.
  3. 最重要的一点, 不要把 拿 a > b , a == b 的结果 想当然的去和 a >= b 建立联系. 正确的符合最初设计思想的关系是 a > b 与 a >= b是一组 . a == b 和其他相等运算符才是一组. 比如 a === b , a != b, a !== b .

在这里插入图片描述