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 內存進行徹底的拷貝。

相關文章
相關標籤/搜索