天天看點

JS-資料類型與結構

一、資料類型

   基本資料類型

        基本類型存儲的值

  • Boolean (布爾類型)
  • Undefined (為定義)
  • Number (數字類型)
  • Null (空)
  • String (字元串類型)
  • Symbol (符号類型)

  對象類型/引用類型

        對象在邏輯上是屬性的無序集合,是存放各種值的容器。對象值存儲的是引用位址,是以和基本類型值不可變的特性不同,對象值是可變的。

  • Object
  • Function
  • Array

例: 

var foo = 1;
var bar = 2;

var obj = {foo: 1, bar: 2}
           

         這裡聲明的三個屬性,基本類型存儲在棧中,引用類型存在堆中,我們常用的var、let和const實際上是指針關系,指向棧和堆中的資料集

        但是const指向最外層的指針(例:0x0203),切不允許修改指針的指向關系,是以object可以修改内部的屬性值,但是不能修改最外層的對象(會導緻修改指向關系),其他基本資料本身就一層資料接口,是以更加不可修改

JS-資料類型與結構

 二、深拷貝和淺拷貝

      1.淺拷貝

        淺拷貝是将對象第一層的每個屬性進行依次複制,但是當對象的屬性是引用類型時,實質複制的是其引用,當引用對象指向的值改變時也會跟着變化

      2.深拷貝

        深拷貝複制變量值,對于非基本類型的變量,則遞歸至基本類型的變量後,再複制。深拷貝的對象與原來的對象是完全隔離的,互不影響,對一個對象的修改并不會影響另一個對象。

實際執行:

var objBase = {
    name: '小明',
    age: 12,
    like: {
        work: '程式設計',
        sport: '跑步'
    },
    say: function() {
        return `${this.name}說:我喜歡${this.like.work}`
    }
}

// 1.0 JSON序列化和反序列化
var objNew1 = JSON.parse(JSON.stringify(objBase))

// 2.0 遞歸拷貝
function deepClone(obj, hash = new WeakMap()) { 
    if (obj instanceof RegExp) return new RegExp(obj)
    if (obj instanceof Date) return new Date(obj)
    if (obj === null || typeof obj !== 'object') {
        // 不是複雜類型,直接傳回
        return obj
    }
    if (hash.has(obj)) {
        return hash.get(obj)
    }
    /**
     * 如果obj是數組,那麼 obj.constructor 是 [Function: Array]
     * 如果obj是對象,那麼 obj.constructor 是 [Function: Object]
     */
    let t = new obj.construtor()
    hash.set(obj, t)
    for (let key in obj) {
        // 遞歸
        if (obj.hasOwnProperty(key)) { //是否是自身的屬性
            t[key] = deepClone(obj[key], hash)
        }
    }
    return t
}

var objNew2 = deepClone(objBase)
           

三、資料類型判斷

     1. typeof

        這個方法是多數開發者最熟知的,對于基本資料類型判斷很友善準确,但是對于複雜的資料類型是有缺點的,比如:

typeof 'seymoe'    // 'string'
typeof true        // 'boolean'
typeof 10          // 'number'
typeof Symbol()    // 'symbol'
typeof null        // 'object' 無法判定是否為 null
typeof undefined   // 'undefined'

typeof {}           // 'object'
typeof []           // 'object'
typeof(() => {})    // 'function'

           

         對于數組和對象的判斷,實際上是不準确的,統一識别成' object '類型

      2.instanceof

        這個方法是依據原型鍊去做判斷,但是實際上也是有問題的,比如:

[] instanceof Array            // true
({}) instanceof Object         // true
(()=>{}) instanceof Function   // true

let arr = []
let obj = {}
arr instanceof Array    // true
arr instanceof Object   // true
obj instanceof Object   // true
           

    arr

數組相當于

new Array()

出的一個執行個體,是以

arr.__proto__ === Array.prototype

,又因為

Array

屬于

Object

子類型,即

Array.prototype.__proto__ === Object.prototype

,是以

Object

構造函數在

arr

的原型鍊上。是以

instanceof

仍然無法準确判斷一個值到底屬于數組還是普通對象 

      3.Object.prototype.toString()

Object.prototype.toString.call({})              // '[object Object]'
Object.prototype.toString.call([])              // '[object Array]'
Object.prototype.toString.call(() => {})        // '[object Function]'
Object.prototype.toString.call('hello world')        // '[object String]'
Object.prototype.toString.call(1)               // '[object Number]'
Object.prototype.toString.call(true)            // '[object Boolean]'
Object.prototype.toString.call(Symbol())        // '[object Symbol]'
Object.prototype.toString.call(null)            // '[object Null]'
Object.prototype.toString.call(undefined)       // '[object Undefined]'

Object.prototype.toString.call(new Date())      // '[object Date]'
Object.prototype.toString.call(Math)            // '[object Math]'
Object.prototype.toString.call(new Set())       // '[object Set]'
Object.prototype.toString.call(new WeakSet())   // '[object WeakSet]'
Object.prototype.toString.call(new Map())       // '[object Map]'
Object.prototype.toString.call(new WeakMap())   // '[object WeakMap]'
           

        這個方法雖然最準确,但是實際上還是需要注意:

  • 該方法本質是通過

    Object.prototype.toString()

     方法得到對象内部屬性 

    [[Class]]

  • 傳入原始類型卻能夠判定出結果是因為對值進行了包裝
  • null

     和 

    undefined

     能夠輸出結果是内部實作有做處理

 四、資料類型轉

     1. Number、String、Boolean

        這三個是我們最常用的,對幾種基本資料類型做轉化的方式

     2.toString - Object.prototype.toString()

    toString()

方法傳回一個表示該對象的字元串。每個對象都有一個

toString()

方法,當對象被表示為文本值時或者當以期望字元串的方式引用對象時,該方法被自動調用,

****  valueOf()

toString()

在特定的場合下會自行調用。* * * * 

      3.valueOf - 

Object.prototype.valueOf()

    valueOf()

方法傳回指定對象的原始值。

JS

調用

valueOf()

方法用來把對象轉換成原始類型的值(數值、字元串和布爾值)。但是我們很少需要自己調用此函數,

valueOf

方法一般都會被

JS

 自行調用。不同對象的

valueOf

實作:

  • String => 傳回字元串值
  • Number => 傳回數字值
  • Date => 傳回一個數字,即時間值,字元串中内容是依賴于具體實作的
  • Boolean => 傳回Boolean的this值
  • Object => 傳回this

       4.隐式類型轉換(這個有機會我再補下)

        最後留下一題:

var a = ?;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

// 當a在什麼情況下,能列印出來 1
           

答案

繼續閱讀