JS數(shù)據(jù)類(lèi)型與拷貝

一左腔、JS的基本數(shù)據(jù)類(lèi)型

  • 基本數(shù)據(jù)類(lèi)型:String,Boolean捅儒,Number液样,Undefined,Null巧还;
  • 引用數(shù)據(jù)類(lèi)型:Object(Array鞭莽,Date,RegExp狞悲,F(xiàn)unction)撮抓;
  • 基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型的區(qū)別:
    1、保存位置不同:基本數(shù)據(jù)類(lèi)型保存在棧內(nèi)存中摇锋,引用數(shù)據(jù)類(lèi)型保存在堆內(nèi)存中丹拯,然后在棧內(nèi)存中保存了一個(gè)對(duì)堆內(nèi)存中實(shí)際對(duì)象的引用,即數(shù)據(jù)在堆內(nèi)存中的地址荸恕,JS對(duì)引用數(shù)據(jù)類(lèi)型的操作都是操作對(duì)象的引用而不是實(shí)際的對(duì)象乖酬,例如復(fù)制的實(shí)質(zhì)是復(fù)制了地址,因而它們指向了同一個(gè)堆內(nèi)存對(duì)象融求;
    為什么基本數(shù)據(jù)類(lèi)型保存在棧中咬像,而引用數(shù)據(jù)類(lèi)型保存在堆中?
    1)堆比棧大生宛,棧比堆速度快县昂;
    2)基本數(shù)據(jù)類(lèi)型比較穩(wěn)定,而且相對(duì)來(lái)說(shuō)占用的內(nèi)存邢菥恕倒彰;
    3)引用數(shù)據(jù)類(lèi)型大小是動(dòng)態(tài)的,而且是無(wú)限的莱睁,引用值的大小會(huì)改變待讳,不能把它放在棧中,否則會(huì)降低變量查找的速度仰剿,因此放在變量棿吹空間的值是該對(duì)象存儲(chǔ)在堆中的地址,地址的大小是固定的南吮,所以把它存儲(chǔ)在棧中對(duì)變量性能無(wú)任何負(fù)面影響琳彩;
    4)堆內(nèi)存是無(wú)序存儲(chǔ),可以根據(jù)引用直接獲取汁针;

按引用訪問(wèn):js不允許直接訪問(wèn)保存在堆內(nèi)存中的對(duì)象术辐,所以在訪問(wèn)一個(gè)對(duì)象時(shí),首先得到的是這個(gè)對(duì)象在堆內(nèi)存中的地址施无,然后再按照這個(gè)地址去獲得這個(gè)對(duì)象中的值辉词;

2、使用typeof可以返回基本數(shù)據(jù)類(lèi)型猾骡,但是NULL類(lèi)型會(huì)返回object瑞躺,因此null值表示一個(gè)空對(duì)象指針;引用數(shù)據(jù)類(lèi)型使用typeof會(huì)返回object兴想,此時(shí)需要使用instanceof來(lái)檢測(cè)

typeof 1   //number
typeof new Number(1) //object
1 instanceof Number //false
new Number(1) instanceof Number //true

其中1是基本數(shù)據(jù)類(lèi)型幢哨,不是引用數(shù)據(jù)類(lèi)型,因此instanceof總為false
通過(guò)new Number(1)包裝以后成為引用數(shù)據(jù)類(lèi)型嫂便,可以判斷為Number

3捞镰、引用數(shù)據(jù)類(lèi)型 (注意,例如new Boolean(false)和false是不===的,但是經(jīng)過(guò)JSON轉(zhuǎn)換后,丟失了constructor,變?yōu)槠胀ǖ膄alse)

  • ES6新增數(shù)據(jù)類(lèi)型:Map,Set毙替,Generator岸售,Symbol
  • 本地對(duì)象:ECMA-262 把本地對(duì)象(native object)定義為“獨(dú)立于宿主環(huán)境的 ECMAScript 實(shí)現(xiàn)提供的對(duì)象”,即本地對(duì)象就是 ECMA-262 定義的類(lèi)(引用類(lèi)型)厂画;
  • 宿主對(duì)象:宿主”就是我們網(wǎng)頁(yè)的運(yùn)行環(huán)境凸丸,即“操作系統(tǒng)”和“瀏覽器”,所有非本地對(duì)象都是宿主對(duì)象(host object)袱院,即由 ECMAScript 實(shí)現(xiàn)的宿主環(huán)境提供的對(duì)象屎慢,所有的BOM和DOM對(duì)象都是宿主對(duì)象,因?yàn)槠鋵?duì)于不同的“宿主”環(huán)境所展示的內(nèi)容不同忽洛,即ECMAScript官方未定義的對(duì)象都屬于宿主對(duì)象腻惠,因?yàn)槠湮炊x的對(duì)象大多數(shù)是自己通過(guò)ECMAScript程序創(chuàng)建的對(duì)象;
  • JS內(nèi)置對(duì)象:是指JS語(yǔ)言自帶的一些對(duì)象欲虚,供開(kāi)發(fā)者使用妖枚,這些對(duì)象提供了一些常用的或是最基本而必要的功能;
    1苍在、Arguments:函數(shù)參數(shù)集合;
    2荠商、Array對(duì)象:length,instanceof,isArray(),toString()返回字符串,valueOf()返回?cái)?shù)組的值,join()可以將數(shù)組轉(zhuǎn)為字符串,push(),pop(),shift(),unshift(),reverse(),sort(),
    slice(),splice(),indexOf(),lastIndexOf(),迭every(),filter(),forEach(),map(),some(),
    歸并方法reduce(),reduceRight()寂恬;
    3、Boolean:布爾對(duì)象莱没;
    4初肉、Error:異常對(duì)象;
    5饰躲、Number:數(shù)值對(duì)象牙咏;
    6臼隔、String對(duì)象:length,charAt()返回指定位置的字符,concat(),slice(),subString(),
    subStr(),indexOf(),lastIndexOf(),trim(),toLowerCase(),toUpperCase(),split(),
    text.match(),text.splice();
    7妄壶、Date對(duì)象:toUTCstring(),getTime()摔握;
    8、RegExp對(duì)象:test()丁寄;
    9氨淌、Function對(duì)象:arguments,this,apply(this,arguments),call(this,num1,num2);
    10伊磺、Math對(duì)象:min(),max(),ceil(),floor(),round(),random()盛正;
    11、Global對(duì)象:encodeURI,encodeURIComponent屑埋,parseInt(),eval()豪筝;
    12、Object對(duì)象:prototype,constructor摘能;
  • 基本包裝類(lèi)型:Boolean,Number,String
    為了便于操作“基本類(lèi)型值”续崖,JS 提供了 三個(gè) 特殊的引用類(lèi)型:Boolean、Number徊哑、String袜刷。這些類(lèi)型和其他引用類(lèi)型相似,但同時(shí) 也具備與各自基本類(lèi)型相應(yīng)的特殊行為莺丑。實(shí)際上:每當(dāng)讀取一個(gè)基本類(lèi)型值的時(shí)候著蟹, “后臺(tái)就會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的基本包裝類(lèi)型的對(duì)象”,從而能夠調(diào)用一些方法來(lái)操作這些數(shù)據(jù)梢莽。
    當(dāng)通過(guò)直接賦值方式創(chuàng)建時(shí),具有基本類(lèi)型的性質(zhì),無(wú)法動(dòng)態(tài)添加屬性和方法萧豆。
    當(dāng)通過(guò)New修飾符創(chuàng)建時(shí),屬于引用類(lèi)型,可以動(dòng)態(tài)添加屬性和方法昏名。

二涮雷、賦值、淺拷貝與深拷貝

賦值

賦的其實(shí)是該對(duì)象的在棧中的地址轻局,而不是堆中的數(shù)據(jù)洪鸭。也就是兩個(gè)對(duì)象指向的是同一個(gè)存儲(chǔ)空間,兩個(gè)對(duì)象是完全聯(lián)動(dòng)的仑扑。

淺拷貝

按位拷貝對(duì)象览爵,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝镇饮。如果屬性是基本類(lèi)型蜓竹,拷貝的就是基本類(lèi)型的值;如果屬性是內(nèi)存地址(引用類(lèi)型),拷貝的就是內(nèi)存地址 俱济,因此如果其中一個(gè)對(duì)象改變了這個(gè)地址嘶是,就會(huì)影響到另一個(gè)對(duì)象。

  1. Object.assign()和數(shù)組的slice()蛛碌、concat() 僅對(duì)基本類(lèi)型數(shù)據(jù)進(jìn)行了深拷貝

  2. 擴(kuò)展運(yùn)算符

let bar = {...baz};
  1. 遍歷賦值
function shallowCopy(src) {
   var dst = {};
   for (var prop in src) {
       if (src.hasOwnProperty(prop)) {
           dst[prop] = src[prop];
       }
   }
   return dst;
}
深拷貝

創(chuàng)造一個(gè)一模一樣的對(duì)象聂喇,新對(duì)象跟原對(duì)象不共享內(nèi)存,修改不會(huì)互相影響左医。

  1. JSON.parse(JSON.stringify()) 可以部分實(shí)現(xiàn)深拷貝,但會(huì)失去constructor,凡是undefined授帕、function、symbol浮梢、Map, Set, RegExp, Date, ArrayBuffer 等內(nèi)置類(lèi)型在進(jìn)行序列化時(shí)會(huì)丟失,Boolean跛十、Number、String等基本包裝類(lèi)型會(huì)變成普通的基本數(shù)據(jù)類(lèi)型秕硝。此外不能處理多重嵌套芥映。
let a = {};
let b = {a};
a.b = b;
let copy = JSON.parse(JSON.stringify(a));//報(bào)錯(cuò)
  1. 采用函數(shù)庫(kù)lodash提供的_.cloneDeep進(jìn)行深拷貝
var obj2 = _.cloneDeep(obj1);
  1. 采用jquery提供的$.extend進(jìn)行深拷貝
var obj2 = $.extend(true, {}, obj1);
  1. 利用MessageChannel發(fā)送并接收消息,作為復(fù)制結(jié)果。缺點(diǎn)是該操作為異步,且依然不支持function远豺。
function structuralClone(obj) {
    return new Promise(resolve =>{
        const {port1, port2} = new MessageChannel();
        //兩個(gè)port可以互相通過(guò)onmessage ,監(jiān)聽(tīng)到對(duì)方postMessage的內(nèi)容
        port2.onmessage = ev => resolve(ev.data);
        port1.postMessage(obj);
    })
}
const obj = /* ... */;
structuralClone(obj).then(res=>{
     console.log(res);
})
  1. 利用history api中的history.state傳遞并接收數(shù)據(jù),作為復(fù)制結(jié)果奈偏。該方法是同步的,但有些瀏覽器對(duì)調(diào)用頻率有限制。
  2. 遍歷對(duì)象躯护、數(shù)組直到都是基本數(shù)據(jù)類(lèi)型惊来,然后再進(jìn)行復(fù)制
   // 定義檢測(cè)數(shù)據(jù)類(lèi)型的功能函數(shù)
   function checkedType(target) {
     return Object.prototype.toString.call(target).slice(8, -1)
   }
   // 實(shí)現(xiàn)深度克隆---對(duì)象/數(shù)組
   function clone(target) {
     // 判斷拷貝的數(shù)據(jù)類(lèi)型
     // 初始化變量result 成為最終克隆的數(shù)據(jù)
     let result, targetType = checkedType(target)
     if (targetType === 'object') {
       result = {}
     } else if (targetType === 'Array') {
       result = []
     } else {
       return target
     }
     // 遍歷目標(biāo)數(shù)據(jù)
     for (let i in target) {
       // 獲取遍歷數(shù)據(jù)結(jié)構(gòu)的每一項(xiàng)值。
       let value = target[i]
       // 判斷目標(biāo)結(jié)構(gòu)里的每一值是否存在對(duì)象/數(shù)組
       if (checkedType(value) === 'Object' ||
         checkedType(value) === 'Array') { //對(duì)象/數(shù)組里嵌套了對(duì)象/數(shù)組
         // 繼續(xù)遍歷獲取到value值
         result[i] = clone(value)
       } else { 
        // 獲取到value值是基本的數(shù)據(jù)類(lèi)型或者是函數(shù)棺滞。
         result[i] = value;
       }
     }
     return result
   }

   // 定義檢測(cè)數(shù)據(jù)類(lèi)型的功能函數(shù)
   function checkedType(target) {
     return Object.prototype.toString.call(target).slice(8, -1)
   }
   // 實(shí)現(xiàn)深度克隆---對(duì)象/數(shù)組
   function clone(target) {
     // 判斷拷貝的數(shù)據(jù)類(lèi)型
     // 初始化變量result 成為最終克隆的數(shù)據(jù)
     let result, targetType = checkedType(target)
     if (targetType === 'object') {
       result = {}
     } else if (targetType === 'Array') {
       result = []
     } else {
       return target
     }
     // 遍歷目標(biāo)數(shù)據(jù)
     for (let i in target) {
       // 獲取遍歷數(shù)據(jù)結(jié)構(gòu)的每一項(xiàng)值裁蚁。
       let value = target[i]
       // 判斷目標(biāo)結(jié)構(gòu)里的每一值是否存在對(duì)象/數(shù)組
       if (checkedType(value) === 'Object' ||
         checkedType(value) === 'Array') { 
          // 對(duì)象/數(shù)組里嵌套了對(duì)象/數(shù)組
          // 繼續(xù)遍歷獲取到value值
         result[i] = clone(value)
       } else { 
         // 獲取到value值是基本的數(shù)據(jù)類(lèi)型或者是函數(shù)。
         result[i] = value;
       }
     }
     return result
   }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末继准,一起剝皮案震驚了整個(gè)濱河市枉证,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌移必,老刑警劉巖室谚,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異崔泵,居然都是意外死亡秒赤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)憎瘸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)倒脓,“玉大人,你說(shuō)我怎么就攤上這事含思。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵含潘,是天一觀的道長(zhǎng)饲做。 經(jīng)常有香客問(wèn)我,道長(zhǎng)遏弱,這世上最難降的妖魔是什么盆均? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮漱逸,結(jié)果婚禮上泪姨,老公的妹妹穿的比我還像新娘。我一直安慰自己饰抒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著嘴拢,像睡著了一般优幸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枣宫,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天婆誓,我揣著相機(jī)與錄音,去河邊找鬼也颤。 笑死洋幻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的翅娶。 我是一名探鬼主播文留,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼故觅!你這毒婦竟也來(lái)了厂庇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤输吏,失蹤者是張志新(化名)和其女友劉穎权旷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贯溅,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拄氯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了它浅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译柏。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖姐霍,靈堂內(nèi)的尸體忽然破棺而出鄙麦,到底是詐尸還是另有隱情典唇,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布胯府,位于F島的核電站介衔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骂因。R本人自食惡果不足惜炎咖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寒波。 院中可真熱鬧乘盼,春花似錦、人聲如沸俄烁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)猴娩。三九已至阴幌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卷中,已是汗流浹背矛双。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蟆豫,地道東北人议忽。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像十减,于是被迫代替她去往敵國(guó)和親栈幸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容