JS 里的数据类型转换

以前的博客介绍了JS中的各类数据类型,那么在js当中,不一样的数据类型怎么相互转换呢,如下是常见的不一样数据类型转换的用法。git

任意类型转字符串

  • x.toString()
(1).toString()  // '1'
true.toString()  // 'true'
null.toString()  // 报错
undefined.toString()  // 报错
({}).toString()  // "[object Object]"
复制代码

toString 方法适用于 number 类型和 boolean 类型,可是对于 nullundefined,使用这种方法会报错,对于 objecttoSring 方法结果不正确,结果永远是 "[object Object]"面试

console.log 其实就是用的这个原理,理论上 console.log 只能接受字符串。浏览器

console.log 打印出来的实际上是有引号的可是浏览器没打, console.log(1) 打印出来的至关于 console.log((1).toString)

因此 console.log 若是发现不是字符串,会自动调用 toString 这个API 转化为字符串, objectkey 也是会这样。

  • String(x)

String() 该方法适用于全部数据类型(除了对象,结果同toString())bash

String(1)  // '1'
String(true)  // 'true'
String(null)  // 'null'
String(undefined)  // 'undefined'
String({})  // "[object Object]"
复制代码
  • x + ''

使用+运算符加上空字符串,功能更强大,能够 +null 和 +undefined。网络

1 + ''  // '1'
true + ''  // 'true'
obj+"";  // "[object Object]"
'' + null  // 'null'
'' + undefined  // 'undefined'
1 + '1'  // '11'
复制代码

+ 若是发现左右任意一边有字符串,它就会尝试把另一边也变成字符串,+ 老是但愿能够获得两个字符串。函数

1 + '1' 因为 + 只能加相同类型的东西,因此它会尝试去改变这个类型,优先会尝试转化为字符串,等价于 (1).toString + '1'spa

任意类型转布尔

  • Boolean(x)
Boolean(123); // true
Boolean("abc"); // true
Boolean({}); // true
Boolean(''); // false
复制代码
  • !!x

用任何东西取反两次就会获得一个 Boolean操作系统

!!"abc" ; // true
!!'' ; // false
!!{} ; // true
复制代码
  • falsy 值

falsy 是在 Boolean 上下文中认定可转换为 false 的值;3d

0 、 NaN 、 null 、 undefined 、‘’(空字符串)、false
复制代码

任意类型转数字

  • Number()

使用 Number 函数,能够将任意类型的值转化成数值。若是没法转换为数字,那么 Number() 函数返回 NaNcode

Number(123) // 123
Number('123') // 123
Number(true) // 1
Number(null) // 0
Number('123.45#') // NaN
复制代码
  • parseInt()

parseInt 方法用于将字符串转为整数。

parseInt('123') // 123
复制代码

若是字符串头部有空格,空格会被自动去除。

parseInt(' 81') // 81
复制代码

若是 parseInt 的参数不是字符串,则会先转为字符串再转换。

parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1
复制代码

字符串转为整数的时候,是一个个字符依次转换,若是遇到不能转为数字的字符,就再也不进行下去,返回已经转好的部分。

parseInt('8a') // 8
复制代码
  • parseFloat()

parseFloat 方法用于将一个字符串转为浮点数。

parseFloat('3.14') // 3.14
复制代码

若是字符串符合科学计数法,则会进行相应的转换。

parseFloat('314e-2') // 3.14
复制代码

若是字符串包含不能转为浮点数的字符,则再也不进行日后转换,返回已经转好的部分。

parseFloat('3.14more non-digit characters') // 3.14
复制代码

parseFloat 方法会自动过滤字符串前导的空格。

parseFloat('\t\v\r12.34\n ') // 12.34
复制代码

若是参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN

parseFloat([]) // NaN
复制代码
  • x - 0
123 - 0
复制代码
  • +x(取正)
+ 123  // 123
+ '-1'  // -1
复制代码

JS数据在内存中的存储方式

什么是内存呢,举个例子:你买一个8G 的内存条,操做系统开机即占用 512MB,Chrome 打开即占用 1G 内存, Chrome 各每一个网页分配必定数量的内存, 这些内存要分给页面渲染器、网络模块、浏览器外壳和 JS 引擎(V8引擎)。 JS 引擎将内存分为代码区和数据区, 咱们只研究数据区。 数据区分为 Stack(栈内存)和 Heap(堆内存)。 简单类型的数据(如Number,string等)直接存在 Stack 里, 复杂类型的数据(object对象)是把 Heap 地址存在 Stack 里。

对象的存储方式是在stack内存存储一个地址,造成对对象的引用,地址指向heap内存的某个位置,这样才能达到能够随时为对象添加或删除内容的目的。因此有句话这么说,object是对象的引用。它在stack内存存的是地址,而不像其余数据类型直接把内容存在stack内存。

关于内存的面试题

  • 题目一
var a = 1
    var b = a
    b = 2
    请问 a 显示是几? 
复制代码

在内存图能够看出 a 仍是等于 1

  • 题目二
var a = {name: 'a'}
    var b = a
    b = {name: 'b'}
    请问如今 a.name 是多少?
复制代码

等于号制做一件事情,就是把右边的东西存到左边,由内存图能够看出 a.name'a'

  • 题目三
var a = {name: 'a'}
    var b = a
    b.name = 'b'
    请问如今 a.name 是多少?
复制代码

在内存图能够看出 a.name'b'

  • 题目四
var a = {name: 'a'}
    var b = a
    b = null
    请问如今 a 是什么?
复制代码

基本类型在栈内存中,对象是复杂类型在堆内存中,因此 a 是等于自己。

  • 题目五
var a = {n:1};  
    var b = a; 
    a.x = a = {n:2};  
    alert(a.x);
    alert(b.x);
复制代码

浏览器看到 a.x = a = {n:2}; 的时候会先肯定 a 的值, a 是内存地址34,而后申明对象 {n:2} 的内存地址为54,右边的 a 就等于内存54了,而前面的 a 已经肯定了是内存34的对象,不会重复改变 a 的值。浏览器是先看左边,再往右看的,只不过是看了右边以后,算完了再回到左边。

GC 垃圾回收

若是一个对象没有被引用,它就是垃圾,将会被回收。

var fn = function(){}
    document.body.onclick = fn
    fn = null
复制代码

fn 是垃圾将被回收吗?

由内存图能够看到 fn 还被 document 引用,因此不是垃圾不会被回收。

若是如今把页面关了,fn 是垃圾吗?

fn 是垃圾将被回收,由于页面关闭后 document就不存在了,后面的对象失去了引用。里面三个对象相链接,可是外面没有链接,这三个都将被回收。

可是 IE6 有个 BUG,会认为这三个不是垃圾,会把这三个内存一直留着。只要不关闭整个IE,只关掉一个 tab 是没有用的,这样垃圾会愈来愈多,内存不能从新被利用。IE6 没法在页面关闭的时候,正常的把那些 onclick 对应的函数给标记为垃圾。

// 解决方法,把全部的事件监听置为 null
window.onunload = function(){
    document.bady.onclick = null
}
复制代码

这就是所谓的内存泄漏 ,内存泄漏就是因为浏览器的一些bug,使得该被标记为垃圾的没有标记为垃圾,而后内存就会被永久的占用。

浅拷贝 VS 深拷贝

  • 这是一个深拷贝的例子
var a = 1
    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 内存进行彻底的拷贝。

相关文章
相关标签/搜索