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