摘要:棧區(qū)由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。屬性返回對(duì)創(chuàng)建此對(duì)象的構(gòu)造函數(shù)的引用。所有的和都是宿主對(duì)象參考高級(jí)程序設(shè)計(jì)堆和棧的概念和區(qū)別全面解析中的數(shù)據(jù)類型與類型轉(zhuǎn)換
數(shù)據(jù)類型
數(shù)據(jù)類型劃分
javascript中定義了6中基本數(shù)據(jù)類型(原始值類型),和一種復(fù)雜數(shù)據(jù)類型(引用類型),所謂復(fù)雜類型,其本質(zhì)是由無序的名值對(duì)(key:value)組成的。
基本數(shù)據(jù)類型:
String
Number
Boolean
undefined
null
Symbol (ES6 新增)
復(fù)雜數(shù)據(jù)類型
Object
原始值引用值
上面提到了原始值和引用類型,可能有些人對(duì)于引用類型很熟悉,但是原始值卻很陌生實(shí)際上,在ECMAScript中,變量可以存放兩種類型的值,即原始值和引用值。
原始值(primitive value)
原始值是固定而簡(jiǎn)單的值,是存放在棧(stack)中的簡(jiǎn)單數(shù)據(jù)段,也就是說,它們的值直接存儲(chǔ)在變量訪問的位置。
引用值(reference value)
引用值則是比較大的對(duì)象,存放在堆(heap)中的對(duì)象,也就是說,存儲(chǔ)在變量處的值是一個(gè)指針(pointer),指向存儲(chǔ)對(duì)象的內(nèi)存處。所有引用類型都集成自O(shè)bject。
之所以說原始值是固定的,原因是當(dāng)我們對(duì)原始值進(jìn)行一些操作時(shí)結(jié)果返回的都是一個(gè)新的副本,但是對(duì)引用值操作時(shí)可能更改原值。
var str = "asdfghjkl"; var obj = {name:1,age:2}; var str2 = str; var obj2 = obj; str2 = "lkjhgfdsa"; obj2.name= 3; console.log(str,str2,obj,obj2) //asdfghjkl lkjhgfdsa {name: 3, age: 2} {name: 3, age: 2} obj == obj2 //true
通過以上代碼可以明確看出字符串是按值傳遞的,在賦值時(shí)會(huì)新建存儲(chǔ)空間,將str 和 str2 存放在不同的內(nèi)存空間內(nèi),對(duì)象是按引用傳遞的,obj = obj2時(shí)沒有新建堆內(nèi)存空間,而是在棧內(nèi)存中存放標(biāo)識(shí)符和值的引用地址,引用地址與obj的棧值相同,指向堆內(nèi)存中的存儲(chǔ)空間。
同時(shí)可以看到obj == obj2 返回true,這是為什么?
var obj3 = {name:3,age:2} obj == obj3 //false
obj3 與 obj 的屬性和屬性值是一樣的,但是 obj == obj3 卻返回false, obj == obj2 返回true, 這說明引用類型在判斷相等的時(shí)候比較的是指針,即指向?qū)?nèi)存的地址。
提到原始值 引用值 內(nèi)存地址等詞,就不得不提數(shù)據(jù)的存儲(chǔ)空間
數(shù)據(jù)的存儲(chǔ)方式堆棧
之前說到基本類型存儲(chǔ)在棧內(nèi)存中,復(fù)雜類型存儲(chǔ)在堆內(nèi)存中,那么什么是棧,什么是堆?
這里說的堆和棧并不是一種數(shù)據(jù)結(jié)構(gòu),而是指存儲(chǔ)空間,JVM內(nèi)存劃分為:寄存器,本地方法區(qū),方法區(qū),堆內(nèi)存,棧內(nèi)存,我們說的堆棧就是這里的堆內(nèi)存 和 棧內(nèi)存。
棧區(qū)(stack)
由編譯器自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
堆區(qū)(heap)
一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。
堆棧區(qū)別
1.棧內(nèi)存存儲(chǔ)的是局部變量而堆內(nèi)存存儲(chǔ)的是實(shí)體;
2.棧內(nèi)存的更新速度要快于堆內(nèi)存,因?yàn)榫植孔兞康纳芷诤芏蹋?br> 3.棧內(nèi)存存放的變量生命周期一旦結(jié)束就會(huì)被釋放,而堆內(nèi)存存放的實(shí)體會(huì)被垃圾回收機(jī)制不定時(shí)的回收,前提是沒有任何引用。
關(guān)于堆和棧的內(nèi)存空間,這里只是簡(jiǎn)單提起,強(qiáng)調(diào)指內(nèi)存空間并非數(shù)據(jù)結(jié)構(gòu)。
不同數(shù)據(jù)類型的存儲(chǔ)區(qū)別
var a = undefined; var b = null; var c = "asdfg"; var d = 123; var e = true; var f = [1,2]; var g = {name:1,age:2}; var h = g;
下圖解釋不同每一種類型的存儲(chǔ)方式
上圖體現(xiàn)出每種數(shù)據(jù)類型在內(nèi)存中的存儲(chǔ)方式:
基本類型undefined null String Number Boolean 直接將標(biāo)識(shí)符和值存儲(chǔ)在棧區(qū)內(nèi);
復(fù)雜類型對(duì)象,數(shù)組等,棧區(qū)內(nèi)只存放標(biāo)識(shí)符和指向堆內(nèi)存中的對(duì)象的指針,真真的對(duì)象值存儲(chǔ)在堆內(nèi)存中,同一對(duì)象的引用指針相同:g == h;
數(shù)據(jù)類型的判斷方式數(shù)據(jù)類型的判斷有多種方式,下面簡(jiǎn)單介紹
typeof
typeof 用于檢測(cè)數(shù)據(jù)的類型,返回值有
number
string
boolean
undefined
object
function
var u ,a = "asdf",b = 1,c = true,d = {},e = null,f = function(){} typeof a; // string typeof b; //number typeof c; //boolean typeof u; //undefined typeof d; //object typeof e; //object typeof f; //function typeof a == "string" //true typeof a == String //false
以上代碼可以看出
返回值為字符串,并且區(qū)分大小寫;
typeof null 返回 object,因?yàn)閚ull是Object的一種,表示空引用,即棧內(nèi)存儲(chǔ)的指向堆中對(duì)象的指針為空;
typeof 可以判斷function的類型,并且對(duì)于非Object類型的數(shù)據(jù)區(qū)分類型比較方便;
不能區(qū)分Object的 具體類型,如 Array Date
instanceof
instanceof 運(yùn)算符用來測(cè)試一個(gè)對(duì)象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性。
由于js可在多個(gè)frame之間交互,但是每個(gè)frame有自己的全局環(huán)境,所以不同frame和窗口之間Array是不同的,所以無法用 a 環(huán)境下的數(shù)組去判斷是否是 b 環(huán)境下的Array對(duì)象的實(shí)例
var a = "asdffgg"; var b = 1; var c = new String("aaaa"); var arr = [1,2]; var date = new Date(); a instanceof String //false 思考:為什么是false? b instanceof Number //false c instanceof Number //true 思考:a 和 c 同樣是字符串結(jié)果卻不一樣 arr instanceof Array //true arr instanceof Object //true 思考:為什么 Array 和 Object都是true? date instanceof Date //true date instanceof Object //true typeof a //string 字面量的形式 返回基本類型 string typeof c //object new 一個(gè)String的實(shí)例 返回復(fù)雜類型 object
通過以上的代碼段體現(xiàn)出以下特點(diǎn)和弊端:
instanceof 用于檢測(cè)Object類型的對(duì)象,基本類型的字面量值永遠(yuǎn)返回false;
instanceof 由于對(duì)象的繼承關(guān)系,所以只能用來判斷兩個(gè)對(duì)象是否屬于實(shí)例關(guān)系,而不能判斷一個(gè)對(duì)象實(shí)例具體屬于哪種類型
數(shù)組即是Array的實(shí)例,又是Object的實(shí)例的原因詳解:
由于對(duì)象之間存在繼承關(guān)系,所以instanceof 能夠判斷出 [ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最終 Object.prototype.__proto__ 指向了null,標(biāo)志著原型鏈的結(jié)束。這里關(guān)于原型鏈的知識(shí)點(diǎn)不細(xì)說
所以無法判斷實(shí)例對(duì)象具體是Object的哪一種類型。
constructor
constructor 屬性返回對(duì)創(chuàng)建此對(duì)象的構(gòu)造函數(shù)的引用。
當(dāng)定義一個(gè)函數(shù)Fn的時(shí)候,JS引擎會(huì)為其添加一個(gè)原型prototype,并為原型添加一個(gè)constructor屬性,將其指向Fn的引用
實(shí)例f的constructor是指向其構(gòu)造函數(shù)Fn的,所以通過constructor我們可以判斷其構(gòu)造函數(shù)是誰,從而間接的判斷對(duì)象的具體類型
但是由于constructor在實(shí)現(xiàn)繼承的時(shí)候可以被更改,實(shí)質(zhì)更改是由于子類繼承父類的時(shí)候可能重寫了子類的原型prototype,因此使子類的prototype上的constructor發(fā)生變化,因此類型判斷可能不準(zhǔn)確
undefined 和 null沒有constructor屬性
toString
Object.prototype.toString 方法可以返回對(duì)象的內(nèi)部屬性[[Class]],格式為[object,Xxxx],其中Xxxx為具體的類型
Object.prototype.toString.call("") //"[object String]" Object.prototype.toString.call([1]) //"[object Array]" Object.prototype.toString.call(new Date) //"[object Date]"
為什么不調(diào)用對(duì)象的toString方法,而是通過call調(diào)用Object.prototype.toString?
"11".toString() //"11" [1,2].toString() //"1,2" new Date().toString() //"Fri Jun 22 2018 14:44:52 GMT+0800 (CST)"
可以看到字符串輸出的是本身,數(shù)組輸出的是“,”鏈接的數(shù)組字符串,時(shí)間類型輸出的時(shí)間字符串,都不是內(nèi)部屬性[[Class]],原因是實(shí)例的構(gòu)造函數(shù)重寫了toString方法,所以要吊用Object對(duì)象的原型傷的toString方法。
類型轉(zhuǎn)換轉(zhuǎn)數(shù)值類型
顯示轉(zhuǎn)換:Number() parseInt() parseFloat()
向Number 轉(zhuǎn)換規(guī)則 ToNumber
Boolean類型的true false,轉(zhuǎn)成1 和 0
數(shù)值直接轉(zhuǎn)成原始值,即本身
null 轉(zhuǎn)為0,undefined 轉(zhuǎn)為NaN
字符串類型,數(shù)值字符串轉(zhuǎn)為數(shù)值型數(shù)字;空字符串""轉(zhuǎn)為0;非數(shù)字字符串轉(zhuǎn)為NaN
對(duì)象,則調(diào)用對(duì)象的valueOf()方法,按前面規(guī)則轉(zhuǎn)為原始值,如果返回NaN,調(diào)用對(duì)象的toString()方法,返回值再依照前面規(guī)則轉(zhuǎn)數(shù)值
var a = {a:1} Number(11) //11 Number("123") //123 Number(true) //1 Number(null) //0 Number(undefined) //NaN Number("") //0 Number(a) //NaN a.valueOf返回 {a:1},a.toString 返回 "[object,Object]",字符串轉(zhuǎn)數(shù)值 返回NaN
parseInt parseFloat 這里不細(xì)說
隱式轉(zhuǎn)換:操作符
+做為一元操作符,操作數(shù)轉(zhuǎn)化為數(shù)值類型
+作為二元操作符,兩個(gè)操作數(shù)中只要有一個(gè)是字符串類型,那么另一個(gè)也轉(zhuǎn)化成字符串類型
+作為二元操作符,兩個(gè)操作數(shù)均不是字符串類型,那么兩個(gè)操作數(shù)均各自隱式向數(shù)值型轉(zhuǎn)化,然后在計(jì)算
如果數(shù)值計(jì)算的操作符不是+操作符,那么操作數(shù)向數(shù)值轉(zhuǎn)化
轉(zhuǎn)String類型
顯示轉(zhuǎn)換 toString() String()
toString:返回相應(yīng)的字符串表現(xiàn),
向字符串轉(zhuǎn)換規(guī)則 ToString
數(shù)字類型,轉(zhuǎn)為數(shù)字字符串
字符串,返回原值
undefined null,沒有toString方法,可以用String()方法,返回"null"和"undefined"字符串
Boolean 轉(zhuǎn)為"true" "false"
對(duì)象,先調(diào)用toString得到原始值,如果是原始值類型則返回;不是則調(diào)用valueOf,返回結(jié)果如果是原始值類型則返回,不是在做toString調(diào)用,返回結(jié)果
var a = {a:1};var b = 11;var c = "11"; var e = "[1,3]";var d = true a.toString() //"[object,Object]" b.toString() //"11" c.toString() //"11" d.toString() //"true" e.toString() //"1,3"
隱式轉(zhuǎn)換同+操作符數(shù)值轉(zhuǎn)化
轉(zhuǎn)Boolean類型
顯示轉(zhuǎn)換:Boolean()
向Boolean轉(zhuǎn)換規(guī)則:
數(shù)字0,""空字符串,null,undefined,NaN轉(zhuǎn)為false,其余轉(zhuǎn)為true
隱式轉(zhuǎn)換操作符 if
什么是隱式轉(zhuǎn)換?
隱式轉(zhuǎn)換與執(zhí)行環(huán)境和操作符相關(guān),當(dāng)前操作期望某種值的時(shí)候,就會(huì)發(fā)生隱式轉(zhuǎn)換,實(shí)際上面提到的具體規(guī)則點(diǎn)就是隱式轉(zhuǎn)換的過程。
內(nèi)置對(duì)象(本地對(duì)象)、單體內(nèi)置對(duì)象,宿主對(duì)象本地對(duì)象:不依賴于宿主環(huán)境的對(duì)象
Object Array Date Function RegExp String Boolean Number
單體內(nèi)置對(duì)象:由ECMAScript實(shí)現(xiàn)提供的,不依賴于宿主環(huán)境的對(duì)象,這些對(duì)象在ECMAScript程序執(zhí)行前就已經(jīng)存在了
Global(所有不屬于其他任何對(duì)象的屬性和方法都屬于Global,全局變量,方法),Math,一些數(shù)學(xué)公式和計(jì)算方法
宿主對(duì)象:由ECMAScript實(shí)現(xiàn)的宿主環(huán)境提供的對(duì)象,可以理解為:瀏覽器提供的對(duì)象。所有的BOM和DOM都是宿主對(duì)象 , Window
參考javascript 高級(jí)程序設(shè)計(jì)
堆和棧的概念和區(qū)別
全面解析js中的數(shù)據(jù)類型與類型轉(zhuǎn)換
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/95802.html
摘要:變量的分類全局變量可以在任何地方使用的變量局部變量在函數(shù)內(nèi)聲明的變量只在函數(shù)內(nèi)有定義,作用域是局部性的什么時(shí)候使用當(dāng)一個(gè)數(shù)據(jù)需要被反復(fù)使用時(shí),就要先保存在變量中。 第一篇回顧學(xué)習(xí),變量 什么是變量 變量就是在內(nèi)存中刨一個(gè)坑存一個(gè)數(shù)據(jù),再給這個(gè)坑起個(gè)名。為什么要給一個(gè)加引號(hào)呢,因?yàn)镴avaScript是松散類型的,即一個(gè)變量可以用來保存任何類型的數(shù)據(jù)。變量的分類:全局變量:可以在任何地方...
摘要:表示尚未存在的對(duì)象是一個(gè)有特殊意義的值。可以為變量賦值為,此時(shí)變量的值為已知狀態(tài)不是,即。用來初始化變量,清除變量?jī)?nèi)容,釋放內(nèi)存結(jié)果為但含義不同。且它倆與所有其他值比較的結(jié)果都是。,需要兩個(gè)操作數(shù)同時(shí)轉(zhuǎn)為。 轉(zhuǎn)載請(qǐng)聲明出處 博客原文 隨手翻閱以前的學(xué)習(xí)筆記,順便整理一下放在這里,方便自己復(fù)習(xí),也希望你有也有幫助吧 第一課時(shí) 入門基礎(chǔ) 知識(shí)點(diǎn): 操作系統(tǒng)就是個(gè)應(yīng)用程序 只要是應(yīng)用...
摘要:每個(gè)類有三部分構(gòu)成第一部分是構(gòu)造函數(shù)內(nèi),供實(shí)例對(duì)象化復(fù)制用。第二部分是構(gòu)造函數(shù)外,直接通過點(diǎn)語法添加,供類使用,實(shí)例化對(duì)象訪問不到。組合繼承還有一個(gè)要注意的地方在代碼處,將子類原型的屬性指向子類的構(gòu)造函數(shù)。 前言 前一陣面試,過程中發(fā)現(xiàn)問到一些很基礎(chǔ)的問題時(shí)候,自己并不能很流暢的回答出來。或者遇到一些基礎(chǔ)知識(shí)的應(yīng)用,由于對(duì)這些點(diǎn)理解的不是很深入,拿著筆居然什么都寫不出來,于是有了回顧一...
摘要:原始類型數(shù)組,循環(huán)變量不能以數(shù)字開頭,因?yàn)槿绻@樣編譯器則無法區(qū)別數(shù)字和變量。可以直接修改數(shù)組的值如就變成了輸出為循環(huán)和判斷 Part1 原始類型,數(shù)組,循環(huán) Variables 變量不能以數(shù)字開頭,因?yàn)槿绻@樣編譯器則無法區(qū)別數(shù)字和變量。 養(yǎng)成好習(xí)慣每句話后面加分號(hào) Primitive data types 包括Number,String, Boolean, Undefined...
摘要:前言之前說要重頭開始復(fù)習(xí),之前一直都在忙著找工作面試,現(xiàn)在工作也終于是找到了,雖然不那么盡人意,但總算有個(gè)歸屬,一段時(shí)間的適應(yīng)也有了自己穩(wěn)定的時(shí)間規(guī)劃,為了給懶惰捉急的自己一個(gè)前行的動(dòng)力,這一篇的回顧學(xué)習(xí)目錄篇也就這樣提上了日程。 前言 之前說要重頭開始復(fù)習(xí)js,之前一直都在忙著找工作面試,現(xiàn)在工作也終于是找到了,雖然不那么盡人意,但總算有個(gè)歸屬,一段時(shí)間的適應(yīng)也有了自己穩(wěn)定的時(shí)間規(guī)劃...
閱讀 1339·2019-08-30 15:44
閱讀 1391·2019-08-29 18:42
閱讀 446·2019-08-29 13:59
閱讀 783·2019-08-28 17:58
閱讀 2823·2019-08-26 12:02
閱讀 2424·2019-08-23 18:40
閱讀 2415·2019-08-23 18:13
閱讀 3118·2019-08-23 16:27