01.JavaScript基础系列:数据类型及类型转换

核心知识点:类型

数据类型分类

  1. 原始类型:number、string、boolen
  2. 两个特殊原始值:undefined、null
  3. 对象类型:array,object,function...

原始值是不能够修改的,非原始值是能够修改的。javascript

隐式类型转换

  1. 原始类型的数据转换
  2. 对象类型与原始值的转换
  3. toString() 和 valueOf()

数据类型的定义

计算机程序的运行须要对值进行操做,可以表示并操做的值的类型称作数据类型(type)。程序须要将值保存起来以备未来使用时,便将其赋值给一个变量,变量是一个值的符号名称,能够经过名称来得到对值的引用。java

数据类型的分类

原始类型

  • 数字
  • 字符串
  • 布尔值

对象类型

对象是属性的集合,每一个属性都由名/值对构成。web

  • 对象:无序集合
  • 数组:有序集合
  • 函数

两个特殊原始值

  • null(空)
  • undefined(未定义)

另外分类方式

  • 可变类型:值是能够修改的,eg: 对象和数组属于可变类型
  • 不可变类型:值是不能够修改的,eg: 数字、布尔值、字符串、null、undefined 属于不可变类型

IEEE754 标准

IEEE754标准中规定:对于 float 单精度浮点数在机器中,用 1 位表示数字的符号,用 8 位来表示指数,用23 位来表示尾数,即小数部分;对于 double 双精度浮点数在机器中表示用 1 位表示符号,用 11 位表示指数,52 位表示尾数,即小数部分。数组

其中指数域称为阶码,对阶码 E 的计算采用源码的计算方式,32位浮点数的 8bits 的阶码E的取值范围是 0 到 255;64位的浮点数的 11bits 的阶码E的取值范围是 0 到 1023;其中当E为全0或者全1时。浏览器

阶码的二进制位数决定浮点数的表示范围,尾数的二进制位数表示浮点数的精度。以32位浮点数为例,尾数域有23位。那么浮点数以二进制表示的话精度是23位,23位所能表示的最大数是,因此十进制的尾数部分最大数值是8388607函数

1.原始类型:数字

基本概念

JavaScript 中的数字格式,可以表示的整数范围是从 -2 ~ 2,包含边界值。然而须要注意的是 JavaScript 中实际的操做是基于32位整数。
ui

JavaScript 中的算术运算存在溢出、下溢或被零整除时不会报错
  • 溢出

当数字运算结果超过 JavaScript 所能表示的数字上限,结果为一个特殊的无穷大(Infinity)值。一样地,当负值超过了 JavaScript 所能表示的数字下限,结果为一个特殊的负无穷大(-Infinity)值spa

  • 下溢

当运算结果无限接近于零并比 JavaScript 能表示的最小值还小的时候发生的一种情形。这种状况下,JavaScript 将会返回 0。code

  • NaN

零除以零是没有意义的,这种整除运算结果也是一个非数字(not-a-number)值,用 NaN 表示。cdn

案例

0 / 1 						//0
0 / -1 						// -0
0 === -0 					// true
1 / 0						// Infinity
-1 / 0						// -Infinity
Infinity === -Infinity                           // false
Infinity + Infinity  		                 // Infinity
-Infinity - Infinity		                // -Infinity
0 / 0						// NaN
Math.sqrt(-1)				        // NaN
-Infinity + Infinity	                        // NaN
NaN === NaN					// false
isFinite(NaN)				        // false
null + null					// 0
undefined + undefined		                // NaN
复制代码

二进制复杂度和四舍五入错误

JavaScript 采用了 IEEE754 浮点数表示法,这是一种二进制表示法,能够精确地表示分数,好比 1/二、1/8 和 1/1024。遗憾的是,咱们经常使用的分数都是十进制 1/10,1/100等,二进制浮点数表示法并不能准确表示相似 0.1 这样简单的数字。

习题

0.1 + 0.2 !== 0.3 
0.3 - 0.2 !== 0.2 - 0.1
复制代码

2.原始类型:字符串

字符串是一组由16位值组成的不可变的有序序列,每一个字符一般来自 Unicode 字符集。JavaScript 经过字符串类型来表示文本,字符串的长度是其所含 16 位值的个数。

在 JavaScript 中字符串是固定不变的,相似 replace()toUpperCase() 的方法都返回新字符串,原字符串自己并无发生变化。

3.原始类型:布尔值

只有两个值,保留字 true 和 false。JavaScript 程序中的比较语句的结果一般都是布尔值。

undefined、null、0、-0、NaN、'' 在 JavaScript 中会被转换成 false。

4.两个特殊原始值:null 和 undefined

null 表示一个特殊值,经常使用来描述 "空值",对 null 执行 typeof 其结果返回字符串 "object",也就是说,能够将 null 认为是一个特殊的对象值,含义是 "非对象"。

undefined 是预约义的全局变量,他的值是 "未定义",若是函数没有返回任何值,则返回 undefined;引用没有提供实参的函数形参的值也是 undefined。使用 typeof 运算符获得的值是 "undefined"。

5.原始类型的包装对象

数字、布尔值、字符串能够经过 Number()、Boolean()、String() 构造函数建立一个临时对象,方法的调用均是来自这个临时对象,若是试图给其属性赋值,会忽略其操做,修改操做只是发生在临时对象身上,而这个临时对象并未继续保留下来。

存取字符串、数组或布尔值的属性时建立的临时对象称作包装对象。还能够经过 Number()、Boolean()、String() 构造函数来显示建立包装对象。

null 和 undefined 没有包装对象。

s1 = new String('hello')
s1.len = 4
t1 = s1.len 		        // 4

s1 = 'hello'
s1.len = 4
t1 = s1.len 		        // undefined


n1 = 1;
n2 = new Number(n1)
n1 == n2 			// true
n1 === n2 		        // false
typeof n1                       // "number"
typeof n2			// "object"
复制代码

6.不可变的原始值和可变的对象引用

JavaScript 中的原始值(undefined、null、布尔值、数组和字符串)是不可更改的,任何方法都没法更改一个原始值;原始值的比较是值的比较,只有在它们的值相等时,它们才相等。

对象是可变的,它们的值是可修改的;对象的比较均是引用的比较,当且仅当它们引用同一个基本对象时,它们才相等。

类型转换

转换和相等性

因为 JavaScript 能够作灵活的类型转换,所以其 "" 相等运算符也随相等的含义灵活多变。在进行 "" 等于运算符判断两个值是否相等时,会作类型转换。

显式类型转换

最简式的方法是使用 Boolean(),Number(),String() 或 Object() 函数,不经过 new 运算符调用这些函数时,会做为类型转换函数进行类型转换。

Number 类的 toString() 方法能够接收并注入和基数的可选参数。若是不知道此参数,转换规则是基于十进制。

Number 类的 toFixed() 根据小数点后的指定位将数字转换为字符串。

隐式类型转换

  • 若是 "+" 运算符的一个操做数是字符串,它将会把另一个操做数转换为字符串
  • 一元 "+" 运算符将其操做数转换为数字
  • 一元 "!" 运算符将其操做数转换为布尔值并取反

对象转换为原始值

对象转字符串和数字的规则只使用本地对象(native object),不适用宿主对象(eg: web 浏览器定义的对象)

toString()

做用是返回一个反映这个对象的字符串

({a: 1}).toString()     // "[object Object]"

数组类的 toString() 方法将每一个数组元素转为字符串,并在元素直接添加逗号后返回字符串
[].toString()	        // ""
[1, 2].toString()       // "1,2"

函数类的 toString() 方法返回这个函数的实现定义的表示方式
(function f() {fn(1)}).toString()   // "function f() {fn(1)}"

RegExp类的 toString()方法将 RegExp 对象转换为正则表达直接量的字符串
/\d+/.toString()            // "/\d+/"

日期类的 toString() 方法返回一个可读的日期和时间字符串
(new Date()).toString()	    // "Sat Feb 01 2020 21:46:17 GMT+0800 (中国标准时间)"
复制代码

valueOf()

若是存在任意原始值,它就默认将对象转换为表示它的原始值。对于对象来讲,没法真正表示一个原始值,默认返回对象自己。

数组、函数、正则的 valueOf() 默认返回对象自己
({a: 1}).valueOf()      // {a: 1}
[1, 2].valueOf()		// [1, 2]
[].valueOf()			// []
/\d+/.valueOf()			// /\d+/
(function f() {fn(1)}).valueOf()    //  f() {fn(1)}

日期类的 valueOf() 返回时间戳
(new Date()).valueOf()	        // 1580565225890
复制代码
  • 对象到布尔类型转换很是简单,全是 true
  • 对象到字符串
    • 若是对象具备 toString() 方法,且该方法返回是一个原始值,JavaScript 会将方法返回的原始值转换为字符串
    • 若是对象没有 toString() 方法,或这个方法返回值不是原始值,若是具备 valueOf() 且返回值是原始值,会将方法返回的原始值转换为字符串
    • 不然会抛出一个类型错误异常
  • 对象到数字
    • 若是对象具备 valueOf() 方法,且该方法返回是一个原始值,JavaScript 会将方法返回的原始值转换为数字
    • 若是对象没有 valueOf() 方法,或这个方法返回值不是原始值,若是具备 toString() 且返回值是原始值,会将方法返回的原始值转换为数字
    • 不然会抛出一个类型错误异常

"+" 和 "==" 应用的对象(非日期类)到原始值的转换基本上都是对象到数字的转换(首先调用 valueOf());日期对象则使用对象到字符串的转换模式(首先调用 toString())。经过 valueOf 或 toString 返回的原始值被直接使用,而不会被强制转换为数字或字符串。

变量

变量做用域

变量的做用域(scope) 是程序源代码中定义这个变量的区域,在函数内声明的变量和函数参数定义的变量都是局部变量,做用域在函数体内有效。

函数做用域(function scope):变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

声明提早(hoisting): 函数内声明的全部变量在函数体内始终是可见的,即函数里声明的变量会被提早至函数体的顶部。

属性的变量

当声明一个 JavaScript 全局变量时,其实是定义全局对象的一个属性。

  • 当使用 var 声明一个变量时,建立的属性是不可配置的,即不可经过 delete 删除
  • 在非严格模式下,给一个未声明的变量赋值,是可配置的,能够经过 delete 删除

做用域链

每一段 JavaScript 代码都有一个与之关联的做用域链(scope chain),这个做用域链是一个对象列表或链表,这组对象定义了这段代码做用域中的变量。

做用域链由一个全局对象组成,在不包含嵌套的函数体内,做用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。在一个嵌套的函数体内,做用域链上至少有三个对象。

当建立一个函数时,它实际上保存了一个做用域链;当调用这个函数时,它建立了一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个做用域链上,同时建立一个新的更长的表示函数调用做用域的链。

相关文章
相关标签/搜索