javascript 數據類型+變量聲明

昨天寫了本身這三個月以來的面試總結,收到了許多人的喜歡,其實我更多的是把此次找工做看成一個全面複習鞏固的過程,複習資料的獲取一方面是本身總結,另外一方是查看其餘人總結的比較全面的內容,另外若是時間容許的狀況下,仍是很喜歡看書的;javascript

       數據類型判斷以及變量聲明在js中是最基礎的了,在基礎內容中,我會標註一些你們容易忽略的點;java

javascript數據類型

圖1 數據類型腦圖

類型區分

基本類型

  • number 數字類型 包含整數和浮點數
  • string 字符串類型
  • boolean 布爾類型
  • null 表示空值,一般是已聲明的變量未有明確的值的含義
  • undefined 未定義,使用var聲明瞭變量,但未給變量初始化值,那麼這個變量的值就是undefined
  • symbol js新增類型,鍵值對存儲方式,具備惟一性

引用類型

引用類型的大類可分爲Object類型,進行細分能夠分爲Object、Array、Date、Function等;面試

數據存儲方式

正式由於數據存儲方式,因此纔會有了引用類型的身拷貝和淺拷貝;
在js的存儲中,js有兩種的數據存儲方式,基本類型是存儲在棧中,引用類型是存儲在堆中;數組

棧內存

基本數據類型存儲在棧內存中,是按照值進行訪問的;瀏覽器

var a = '1'; //變量對象
var b = 3 //變量對象
var str = '我是變量'
複製代碼
圖2 基礎類型存儲方式

當訪問a的時候,會直接進行值的訪問
當變量的值修改的時候,系統會從新爲其賦值,開闢了一個新的空間存儲值,變量名直接等於變量值,而被修改的原始變量值,會在內存回收中進行回收;markdown

堆存儲

引用類型的值保存在堆內存中的對象,值的大小不固定,棧內存中存放地址,指向堆內存只可以的對象,按照引用進行訪問;函數

var obj = {
  a:2,
  b:33
}
var arr = [
  2,3,4
]
複製代碼

js不容許直接訪問堆內存中的位置,所以咱們不能直接操做對象的堆內存空間。在操做對象時,其實是在操做對象的引用而不是實際的對象。爲此,引用類型的值是按引用訪問的。oop

圖3 堆內存存儲數據方式

所以 當咱們訪問引用類型的時候,是先找到當前存儲值的地址,而後在經過地址訪問到數據的值;post

值的複製

基本類型

變量中的數據發生拷貝的時候,系統會自動爲新的變量分配一個值,最後這些變量都是相互不影響的;測試

var name ='mfy'
var editName = name;
editName = 'yyy'
複製代碼
圖4 基本類型值的複製

複製後的值是系統從新分配的,不會影響到原始被複制的值;

引用類型複製

引用類型的複製又分爲深複製和淺複製; 此時咱們只說淺複製;

var personalMsg ={
  name:'mfy',
  age:22,
  offer:'fy'
}

var clonePer = personalMsg;
personalMsg.name = 'yyy'
複製代碼
圖5 引用類型值的複製

深拷貝仍是淺拷貝

  • 當咱們改變子對象(複製出來的新對象)時,父對象(被拷貝的對象)也會跟着改變的拷貝,稱爲淺拷貝。也就是說,子對象和父對象在淺拷貝的時候他們指向同一個內存的對象。
  • 深度拷貝就是把父對象拷貝到子對象上,並且二者的內存和之後的操做都互不影響的拷貝!

類型轉換

當咱們在使用某些數據變量時候,會自動發生一些類型的轉換;js自己爲弱類型,一般在使用的時候,不當心就會出現類型轉換;

運算符號的隱式轉換

所有都是+號

  • 包含+ - 操做的時候進行轉換
  • 字符串兩邊存在+的時候,相鄰均被轉換成string類型
1+'2' // '12'
1+3+'3' // '43'
'3'+1+2 //'312'
2+1+false // 3
2+1+true  // 4 
3+1+{a:2} // 4[object Object]
複製代碼
  • 保持從前向後的運算順序
  • 存在字符串的時候,會將先後兩個進行類型轉換String
  • 若是+號存在則會將false 轉化成0 true轉化成1
  • 存在引用類型,會將其轉化爲toString格式,在進行相加

存在-號時候

+在字符串使用會當成連接符號,而-則是直接進行類型轉換

1-'2' // -1
1+3-'3' //1 
'3'+1-2 // 29
2+1-false // 3
2+1-true  // 2
3+1-{a:2} // NaN
複製代碼
  • 存在-的時候會將兩邊非數字類型轉化爲數字類型
  • 從前日後計算模式

==比較

  1. x、y均爲number

1 == 1 //true 2. x 、y 類型不相同

1=='1' //true
1==true  //true
複製代碼
  • boolean的時候會被轉化成 0/1

3.存在對象比較時候

1 =={a:3}  //false
1 == {valueOf:()=>{return 1}} //true
複製代碼
  • 存在對象時候,若是對象無valueOf屬性,則直接比較
  • 存在valueOf的時候,則會比較valueOf內容的值;

判斷類型的方式

typeof

主要用於基本數據類型比較,包含基本數據類型

圖6 typeof判斷數據類型

對於null 是瀏覽器一直存在的這個問題

typeof null //"object"
複製代碼

typeof判斷引用類型,判斷引用類型的時候失效了

圖7 typeof判斷引用類型失效

Object.prototype.toString.call(XXX) 引用類型判斷

console.log(
  Object.prototype.toString.call(null),'\n', //[object Null] 
  Object.prototype.toString.call(11),'\n', // [object Number]
  Object.prototype.toString.call(false),'\n', // [object Boolean]
  Object.prototype.toString.call('333'),'\n',  // [object String]
  Object.prototype.toString.call([3,4,2,2]),'\n', // [object Array]
  Object.prototype.toString.call({a:3,b:44}),'\n', // [object Object]
  Object.prototype.toString.call(new RegExp('.*?')),'\n',  //[object RegExp] 
  Object.prototype.toString.call(new Promise((resolve,reject)=>{resolve(2)})),'\n', //[object Promise]
)
複製代碼

此方式可以判斷出不論是引用類型仍是基本類型都可以判斷出來

instanceof

此方式可以判斷的是原型鏈上的連接關係

function Super (){
  this.name = 'myyu'
}
let superNew = new Super();

console.log(superNew instanceof Super) //true

console.log(superNew instanceof Object) //true

console.log(superNew instanceof Array) //false
複製代碼

比較常見的就是

寫instanceof的實現

function myInstanceof(left,right){ 
  if(!right || !left) return false;  
  //左側的實例進行查找
  let pro = left.__proto__;
  //獲取右側的原型
  let prototype = right.prototype;  
  while(pro){
    if(pro == prototype){
      return true
    }
    pro = pro.__proto__;
  }
  return false;
}
複製代碼

其餘方式

判斷數組

Array.isArray([1,2,3]) //判斷是不是數組
isNaN(333) //false 
isNaN(underfined+1) //true
複製代碼

變量聲明

做用域

做用域知識很是重要,內容比較多,這裏只簡單說起,具體的內容後續補充

變量聲明的三種方式

var

可以定義在全局的變量

console.log("全局1:"+golbalA)
 var golbalA = 5;
 console.log("全局2:"+golbalA)

複製代碼
圖8 var變量聲明

定義在函數內部

var 定義聲明的變量是能夠進行變量提高的,所以第一個打印出undefind

console.log("全局1:"+golbalA)
    var golbalA = 5;
    console.log("全局2:"+golbalA)
    function a (){
      console.log(golbalA)
    }
    a()
複製代碼
圖7 var變量聲明在函數內部

全局定義的變量在函數中若是無同名的變量也能夠訪問;

console.log("全局1:"+golbalA)
    var golbalA = 5;
    console.log("全局2:"+golbalA)
    function a (){
      var golbalA =2222
      console.log(golbalA)
    }
    a()

複製代碼
圖8 var函數內部自定義的變量
  • 定義在全局的變量可以在函數做用內訪問
  • 定義在函數內部的變量只能函數內部訪問

let

定義在全局中

console.log("全局1"+letA)
  let letA = "global";
  console.log(letA)
複製代碼

直接告訴咱們不可以進行使用,在變量未初始化以前

圖9 let變量聲明

定義在函數內部中

let letA = "global";
  console.log(letA) //global
  function a(){ 
    console.log(letA)//global
  }
  a()
複製代碼
let letA = "global";
  console.log(letA)//global
  function a(){
    let letA = 'function'
    console.log(letA) //function
  }
  a()
複製代碼
  • 定義在全局的變量可以全局訪問
  • 定義在函數內部的變量外部不能訪問

定義在塊級做用域中

if(true){
    let globala = 'globala'
    var globalb = 'globalb'
  }
  console.log('globala',globala)
  console.log('globalb',globalb)

複製代碼
圖10 let變量聲明

此時就是用let定義在塊級做用域的變量,沒法在塊級之外進行修改;而var是能夠的;

let的暫時性死區

暫時性死區是常常忽略的問題,

var a =222
 if(true){
   a = 33;
   let a =44
 }
複製代碼
圖11 let存在變量聲明
- 只要塊級做用域內存在 let 命令,它所聲明的變量就「綁定」(binding)這個區域,再也不受外部的影響。上面的代碼中,塊級做用域內 let 又聲明瞭一個局部變量 a ,致使後者綁定這個塊級做用域,因此在 let 聲明變量前,對 a 賦值會報錯。 - ES6明確規定,若是區塊中存在 let 和 const 命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。

const

定義常量

const a = 3333;
  console.log(a)
  a= 444
複製代碼
圖12 const定義常量

由const定義的變量是沒法進行更改的

定義變量

const a;
  console.log(a)
複製代碼
圖13 const定義常量必須賦值

修改定義的值

const定義的基礎類型是沒法修改的,可是定義引用數據類型的時候;

const obj ={
    a:22,
    b:444
  }
  console.log(JSON.stringify(obj) )
  obj.a = 'mayy'
  console.log(JSON.stringify(obj) )
複製代碼
圖14 const定義常量能夠修改

const 的暫時性死區

if(true){
   a=3;
   const a=5
 }
複製代碼
圖15 const存在暫時性死區

const 總結

  • const 定義的基本類型常量一旦定義沒法修改
  • const 聲明變量必須進行定義
  • const 存在暫時性死區

變量提高

變量提高其中能夠去排列組合測試下🥳🥳

  • var 存在變量提高,容許在聲明前使用,let、const不可以在進行使用
  • var的變量會掛載到windos上,而let、const不會掛載;
  • let、const只能進行一次變量聲明,後面不能夠在進行聲明同名字的變量
  • const的變量一經賦值,將不會在進行使用,除了引用類型除外;

面試常見問題總結

js數據類型

  • 基本類型和引用類型的區別
  • 存儲方式 堆、棧存儲區別和聯繫
  • nullundefined 的區別
  • 類型方式判斷typeof、instanceof
  • 手寫instanceof實現
  • 類型轉換:隱式轉換強制轉換
  • 引用類型複製、拷貝、深淺拷貝

變量聲明

  • 變量聲明而生成的做用域
  • 暫時性死區 的含義以及生成方式
  • letconst 生成的做用域區間
  • 常見let 、const使用方式

參考文檔

js隱式類型轉換 《javascript 高級程序設計(第四版)》

相關文章
相關標籤/搜索