共计 3400 个字符,预计需要花费 9 分钟才能阅读完成。
一、数据类型转换:
JS 是一门动态类型的语言,变量数据类型没有限制,可以随时赋值,但是运算时是对数据类型有要求的,如果运算类型不符,js 会自动强制转换类型后再进行计算。
‘2’-1
‘2’ 是 string 类型 1 是 number 类型,两个数据类型不同,但是进行了减法运算,运算前 js 会自动尝试将 string 类型转为 number 类型后再进行运算。
二、任意值转字符串:
js 提供了以下 API 进行转换,String(?),?.toString()
var a0 = 0;
var a1 =true;
var a2 = undefined;
var a3 = null;
var a4 = {};
String(a0)
"0"
String(a1)
"true"
String(a2)
"undefined"
String(a3)
"null"
String(a4)
"[object Object]"
a0.toString()
"0"
a1.toString()
"true"
a2.toString()
VM308:1 Uncaught TypeError: Cannot read property 'toString' of undefined
at <anonymous>:1:4
(anonymous) @ VM308:1
a3.toString()
VM315:1 Uncaught TypeError: Cannot read property 'toString' of null
at <anonymous>:1:4
(anonymous) @ VM315:1
a4.toString()
"[object Object]"
通过上述代码可以发现,null,和 undefined 可以用 String 但是不能用 toString,因为他们没有 toString()方法。
var a0 = 0 + '';
var a1 = true + '';
var a2 = undefined + '';
var a3 = null + '';
var a4 = {} + '';
undefined
a0
"0"
a1
"true"
a2
"undefined"
a3
"null"
a4
"[object Object]"
也可以通过加一个空字符串来转成字符串类型,该方法核心在于加号,加号如果发现左右两边任意有字符串,就会尝试将另外一边也转成字符串。
三、任意值转布尔值:
js 提供了以下 Boolean()方法进行转换,还可以通过!! 取反两次进行转换
var a0 = 0;
var a1 = true;
var a2 = undefined;
var a3 = null;
var a4 = {};
undefined
Boolean(a0)
false
Boolean(a1)
true
Boolean(a2)
false
Boolean(a3)
false
Boolean(a4)
true
!!a0
false
!!a1
true
!!a2
false
!!a3
false
!!a4
true
所有的数据类型中,有 5 种特殊值是 false。number 类型的 0 和 NaN 是 false,空字符串‘’也是 false,所有的对象都是 true 即使是空对象也是。
5 个 falsy 值
var a = 0
var a1 = NaN
Boolean(a)
false
Boolean(a1)
false
var a2 = ''
Boolean(a2)
false
var a3 = null
Boolean(a3)
false
var a4 = undefined
Boolean(a4)
false
四、任意值转数值:
js 提供了以下 API 进行转换,
1、Number():
Number()方法会对字符串进行转换,如可以转换成 number 类型则转为对应的数值,如果不能则返回 NaN。
// 空字符串转为 0
Number('') // 0
// 布尔值:true 转成 1,false 转成 0
Number(true) // 1
Number(false) // 0
// undefined:转成 NaN
Number(undefined) // NaN
// null:转成 0
Number(null) // 0
// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc') // NaN
2、parseInt(string, radix),parseFloat(),parseFloat 一般用来转浮点数
string 要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。radix 一个介于 2 和 36 之间的整数(数学系统的基础),表示上述字符串的基数。比如参数 ”10″ 表示使用我们通常使用的十进制数值系统。始终指定此参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当未指定基数时,不同的实现会产生不同的结果,通常将值默认为 10。
Number()函数将字符串转为数值,要比 parseInt()和 parseFloat()函数严格很多。Number()只要有一个字符无法转成数值,整个字符串就会被转为 NaN,而 parseInt()和 parseFloat()会尝试将字符串前面的数字转成数字。如果要转的字符串第一位就无法转换则返回 NaN
var a = '123abc'
Number(a)// 字符串 a,Number 直接返回 NaN
NaN
parseInt(a,10)// 字符串 a,parseInt 则将字符串前面的 123 转成数字
123
parseFloat(a)
123
var a = 'abc123'
parseInt(a,10)
NaN
parseFloat(a)
NaN
除了使用 parseInt(string, radix),parseFloat(),一般多使用【-0】和【+0】方法进行转换
'1'-0
1
'1.21'-0
1.21
'-1'-0
-1
'-1.21'-0
-1.21
五、普通类型和包装对象:
1、所谓“包装对象”,指的是与数值、字符串、布尔值分别相对应的 Number、String、Boolean 三个原始对象。这三个原始对象可以把原始类型的值变成(包装成)对象。
var a = new Number(123);
var b = new String('abc');
var c = new Boolean(true);
var a1 = 123;
var b1 = 'abc';
var c1 = true;
当带有 new 操作符时,是当作对象并且 JS 提供了一些方法,不带 new 声明是,值直接是存在栈内存,带 new 操作符时当对象是存在堆内存。通过下面代码可以看到,通过 new 声明提供了很多方法。
var a = 'a'
var b = new String('b')
console.log(a)
a
console.log(b)
String {"b"}....
六、普通类型(原始对象)和包装对象的转换:
某些场合,原始类型的值会自动当作包装对象调用,即调用包装对象的属性和方法。这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,并在使用后立刻销毁实
var a = 'abc'
// 声明一个普通字符串类型(原始对象),其本身并没有 length 属性
a.length
// 调用 a.length 时 JS 引擎会自动将 var a = 'abc' 转成 var a = new String(a)
3
a.name = 'zhang'
"zhang"
// a 转为包装对象后加了一个 name 属性
a.name
// 但是 a.name 却返回 undefined,这是因为原始类型的值转为包装对象使用后立刻销毁
undefined
七、关于内存的一些知识点:
在 js 普通(简单)数据类型,存到栈内存,复杂类型存到堆内存,string 两者都可以存。
栈内存和堆内存数据组织形式不同。
示例解析:
第一:a 是一个对象,栈内存地址假设是 addr1,值保存在堆内存。
第二:声明变量 b 等于变量 a,则变量 b 也是一个对象,因为 b =a,所以栈内存 b 的地址也
是 addr1,并且堆内存不会重复保存 b 的值。
第三:重新给变量 b 赋值且值是对象类型,此时会在堆内存保存 b 的值。
结果:a.name 返回的是 a,因为 b 第二次赋值时在堆内存已经保存了它的值,a 和 b 在堆内存有各自的值互不影响。
示例解析:
第一:a 是一个对象,栈内存地址假设是 addr1,值保存在堆内存。
第二:声明变量 b 等于变量 a,则变量 b 也是一个对象,因为 b =a,所以栈内存 b 的地址也是 addr1,堆内存不重复保存 b 的值。
第三:变量 a 和 b 两个栈内存地址是相同的,都指向堆内存的地址 addr1,此时修改 a.name 或者 b.name 都会将堆内存数据覆盖。
结果:a.name 返回的是 b,因为 b.name 已经修改了堆内存内保存的数据