JS数据类型转换
1.JS有5种简单数据类型(也称基本数据类型):undefined、null、Boolean、Number和String。还有两种复杂数据类型——symbol(这里不做多介绍)和Object,对象本质上是由一组无序的名值对组成的,ECMAScring不支持任何创建自定义类型的机制,而所有值最终都将是上述7种数据类型之一。
数据类型的相互转换
1.任意数据类型转字符串
String(x)
String(1)//"1"
String(true)//"true"
String(null)//"null"
String(undefined)//"undefined"
String({})//"[Object Object]"
toString()
(1).toString() //"1"
true.toString() //"true"
null.toString() //Uncaught TypeError: Cannot read property 'toString' of null
// at <anonymous>:1:6
undefined.toString() //Uncaught TypeError: Cannot read property 'toString' of undefined
//at <anonymous>:1:11
{}.toString() //Uncaught SyntaxError: Unexpected token .
({}).toString() //"[object Object]"
老司机用法:x+''
1+'' // "1"
true+'' // 'true'
null+'' // 'null'
undefined+'' // 'undefined'
{}+'' // 0
var o = {}
o+ '' //{object Object}
2.任意数据类型转数字
1.Number(x)
2.parselnt(x,10)
MDN
3.parseFloat(x)
MDN
4.x-0
5.+x
3.任意数据类型转布尔值
1.Boolean(x)
2.!!x
4.五个falsy值
0 NaN '' null undefined .
falsy是在Boolean上下文中认定可转换为false的值。
JavaScript在需要用到布尔类型的上下文中使用强制类型转换(Type Conversion)将值转换为布尔值,比如:在条件语句或循环语句中
5.内存图
- 你买一个 8G 的内存条
- 操作系统开机即占用 512MB
- Chrome 打开即占用 1G 内存
- Chrome 各每个网页分配一定数量的内存
- 这些内存要分给页面渲染器、网络模块、浏览器外壳和 JS 引擎(V8引擎)
- JS 引擎将内存分为代码区和数据区
- 我们只研究数据区
*数据区分为 Stack(栈内存) 和 Heap(堆内存) - 简单类型的数据直接存在 Stack 里
- 复杂类型的数据是把 Heap 地址存在 Stack 里
遇到问题就画图,不要分析。
如果将复杂数据类型存放在栈内存里面,那么向其中添加数据就很麻烦、一些数据就需要向后面移动。只需要在栈内存中给代表复杂数据类型(对象)的变量存放一个地址(没有指针,是引用)指向堆内存中的数据。一个变量等于另一个复杂数据类型,就把地址复制给它。
所有的变量和对象都是引用关系。
4个常见的面试题
var a = 1
var b = a
b = 2
请问 a 显示是几? //1
var a = {name: 'a'}
var b = a
b = {name: 'b'}
请问现在 a.name 是多少?//'a'
var a = {name: 'a'}
var b = a
b.name = 'b'
请问现在 a.name 是多少?//'b'
var a = {name: 'a'}
var b = a
b = null
请问现在 a 是什么?//{name: 'a'}
垃圾回收机制
GC 垃圾回收 如果一个对象没有被引用,那么它就是垃圾,将会被回收。
引用包括事件触发引用,如果一个函数被页面上的事件引用了,也不会算作垃圾被回收。
解决办法:将事件赋值null,就表示不再引用。
IE6 BUG 无法正常的在页面关闭时,将没有人引用的垃圾正常的清除。设置window.onunload事件,将所有的事件都设置为null。
内存泄露:表示该被标记为垃圾的数据没有被标记,内存就会被永久的占用。除非把整个浏览器关闭,否则浏览器就会吃很多的内存,无法再分配新的内存用于存储数据。*
深复制是什么鬼
var b = a
b = 2 //这个时候改变 b
a 完全不受 b 的影响
那么我们就说这是一个深复制
对于简单类型的数据来说,赋值就是深拷贝。
对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。
这是一个浅拷贝的例子
var a = {name: 'frank'}
var b = a
b.name = 'b'
a.name === 'b' // true
因为我们对 b 操作后,a 也变了
什么是深拷贝了,就是对 Heap 内存进行完全的拷贝。
var a = {name: 'frank'}
var b = deepClone(a) // deepClone 还不知道怎么实现
b.name = 'b'
a.name === 'a' // true
对于基本类型变量,简单的赋值就是深拷贝。改变一个变量,不影响赋值的变量,两者互不干扰。对于深浅拷贝,一般只讨论复杂数据类型。
复杂类型变量,a等于b,a改变导致b也会改变,这就是浅拷贝。因为只是将stack里面的地址复制了一份而已。复杂数据类型的深拷贝,会拷贝堆内存里面的数据,包括数据内的引用,将不再引用同一个地址,而是引用新拷贝的数据的地址。