JavaScript的數據類型(四)

目錄

1. 基本類型和引用類型

2. 檢測數據類型的方法

3. 數據類型的轉換

4. 通用庫的初步建立與對象的深淺拷貝

5. 小結


從前面三篇文章,咱們已經大體瞭解JavaScript的基本語法中的數據類型——數值型、字符串、布爾型、對象、數組、函數、null和undefined;
這篇文章將深刻探討這幾種數據類型在內存中的存儲方式、讀取方式和拷貝方式;javascript


1.基本類型和引用類型

在以前的文章,咱們瞭解到JavaScript中的變量根據數據的複雜程度可分爲原始數據類型和複雜數據類型;
如今,咱們將從數據內存存儲角度,將變量劃分爲基本類型值和引用類型值;
基本類型值:保存在棧內存的簡單數據段,包括數值、字符串、布爾值、null和undefined;
基本類型值在賦值時,直接將值賦給變量,訪問變量即訪問值,能夠直接操做保存在變量的值;

在進行基本類型值拷貝時,會在變量對象上建立一個新值,而後把值賦給另外一個變量;所以,在改變上述代碼中給a賦b的值後,再改變a的值,將不影響b的值,兩個變量的獨立的;
引用類型值:保存在堆內存中的對象,變量保存的是一個指向內存中對象的指針;
引用類型在賦值時是將保存在堆內存的對象的地址賦給變量,訪問變量實際訪問的是變量的指針,該指針指向對象,在讀寫(增刪改)操做時操做的是實際的對象,但在拷貝時則是指針;

全部由上述代碼可知:在把a賦值給b時實際拷貝的是a的指針,當改變對象的屬性值時,a賦予的對象的屬性值也會改變,由於兩者指向同一對象;
但有時候,咱們但願實現對象的真正拷貝而且切斷引用同一對象的聯繫,具體作法將會在下文具體講解;java


2. 檢測數據類型的方法

要想實現對象的深拷貝,第一步首先要知道數據的類型,否則後續工做將無從下手;
JavaScript中提供檢測數據類型的方法大體有3種:
typeof操做符
typeof操做符可以很好的區分基本類型值(null除外);

但對部分引用類型值就無能爲力,好比它沒法區分object、null和Array,此時就要藉助instanceof操做符
instanceof操做符
instanceof操做符能夠識別某個變量是不是某個對象的實例,藉助這個功能能夠進一步區分object、Array和null三者的區別;

可是,這還不足以區分object和Array,因此還須要藉助第3個方法識別數據類型;
Object.prototype.toString()方法
git


3.數據類型轉換

數據類型轉換以前在前面的文章分散到變量部分講解了一下,這裏爲了文章的系統性,從新將數據類型轉換的方法概括一下:github

3.1 轉換爲數值

任何類型數據轉換爲數值有4種方法:Number()轉型函數、parseInt()parseFloat()+操做符;



上述四種方法的區別在於Number和+做用同樣能夠對任何類型數據進行轉型,而parseInt和parseFloat只能對數值和字符串轉型;數組

3.2 轉換爲字符串

轉換爲字符串包括3種方法:轉型函數String()toString()方法(null和undefined會報錯)和""(做用等同於String());

函數

3.3轉換爲布爾值

轉換爲布爾值有2種方法:轉型函數Boolean()!!
this


4通用庫的初步創建與對象的深淺拷貝

實現對象的深淺拷貝,首先要識別變量的數據類型,上一節咱們已經知道識別數據類型的方法,下面咱們能夠定義識別數據類型的函數並將其封裝在一個對象(通用庫)中;
通用庫的創建spa

(function(window){
  window.Util = (function(){
        // 1.判斷數據類型
            function isNumber(el){
                return typeof el === "number";
            };
            function isString(el){
                return typeof el === "string";
            }
            function isBoolean(el){
                return typeof el === "boolean";
            }
            function isObject(el){
                return Object.prototype.toString.call(el) === "[object Object]"
            };
            function isArray(el){
                return Object.prototype.toString.call(el) === "[object Array]"
            };
            function isSimpleType(el){
                return this.isNumber(el) || this.isString(el) || this.isBoolean(el)
            };
    return {
            isNumber:isNumber,
            isString:isString,
            isBoolean:isBoolean,
            isObject:isObject,
            isArray:isArray,
            isSimpleType:isSimpleType,
    }
  })();
})(window);

上述代碼首先使用數據類型判斷的方法判斷傳入的參數的數據類型;prototype

//對象或數組的拷貝
            function shallowCopy(oldObj){
                var newObj = {};
                for(var key in oldObj){
                    if(!this.isSimpleType(oldObj[key])){
                        return "It doesn't match shallowCopy"
                    }
                    newObj[key] = oldObj[key]
                }
                return newObj;
            };    
            function cloneObject(oldObj){
                var newObj = {};
                for(var key in oldObj){
                    if(this.isObject(oldObj[key])){
                        newObj[key] = cloneObject(oldObj[key])
                    }else if(this.isArray(oldObj[key])){
                        newObj[key] = cloneArray(oldObj[key])
                    }else if(this.isSimpleType(oldObj[key])){
                        newObj[key] = oldObj[key]
                    }
                }
                return newObj;
            };
            function cloneArray(oldArr){
                var newArr = [];
                for(var i = 0;i<oldArr.length;i++){
                    if(this.isArray(oldArr[i])){
                        newArr.push(this.cloneArray(oldArr[i]))
                    }else if(this.isObject(oldArr[i])){
                        newArr.push(this.cloneObject(oldArr[i]))
                    }else if(this.isSimpleType(oldArr[i])){
                        newArr.push(oldArr[i])
                    }
                }
                return newArr;
            };
            function deepCopy(oldObj){
                var newObj = {};
                for(var key in oldObj){
                    if(this.isSimpleType(oldObj[key])){
                        newObj[key] = oldObj[key]
                    }else if(this.isObject(oldObj[key])){
                        newObj[key] = this.cloneObject(oldObj[key])
                    }else if(this.isArray(oldObj[key])){
                        newObj[key] = this.cloneArray(oldObj[key])
                    }
                }
                return newObj;
            }
        return {
            isNumber:isNumber,
            isString:isString,
            isBoolean:isBoolean,
            isObject:isObject,
            isArray:isArray,
            isSimpleType:isSimpleType,
            cloneObject:cloneObject,
            cloneArray:cloneArray,
            shallowCopy:shallowCopy,
            deepCopy:deepCopy    
        }

上面的代碼deepClone方法將對數組或對象的屬性進行遍歷,若是發現屬性值是基本類型,則直接賦值,若是發現是引用類型則調用cloneArray或cloneObject方法,這兩個方法將繼續遍歷引用類型的屬性值,直到遞歸到屬性值是基本類型值,從而完成對象的"深拷貝";
通用庫的代碼地址將發佈在【github】,以供童鞋參考;設計


5.小結

經過閱讀本文,咱們能夠知道:

  • 變量的數據類型根據其在內存中的存儲方式,可分爲基本類型值和引用類型值;

  • 基本類型值是保存在棧內存中的簡單數據段,包括數值、字符串、布爾值、null和undefend,變量保存的是基本類型值的實際值;

  • 引用類型值是保存在堆內存的對象,變量保存的是指向對象的指針;

  • 判斷數據類型的方法包括typeof操做符、instanceof操做符、Object.prototype.toString()方法;

  • 數據類型轉換的方法有轉換爲數值、轉換爲字符串和轉換爲布爾值;

  • 咱們經過創建一個通用庫的方式,封裝對象的深淺拷貝方法;
    最後,JavaScript核心知識點的基本語法部分將暫且告一段落,下一章將進入JavaScript核心知識點的標準庫部分;


參考資料

相關文章
相關標籤/搜索