基礎回顧-javascript數據類型

數據類型

數據類型劃分 javascript

javascript中定義了6中基本數據類型(原始值類型),和一種複雜數據類型(引用類型),所謂複雜類型,其本質是由無序的名值對(key:value)組成的。 java

基本數據類型:程序員

  • String
  • Number
  • Boolean
  • undefined
  • null
  • Symbol (ES6 新增)

複雜數據類型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的棧值相同,指向堆內存中的存儲空間。spa

同時能夠看到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;

下圖解釋不一樣每一種類型的存儲方式

數據類型存儲方式圖

上圖體現出每種數據類型在內存中的存儲方式:

  1. 基本類型undefined null String Number Boolean 直接將標識符和值存儲在棧區內;
  2. 複雜類型對象,數組等,棧區內只存放標識符和指向堆內存中的對象的指針,真真的對象值存儲在堆內存中,同一對象的引用指針相同: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

以上代碼能夠看出

  1. 返回值爲字符串,而且區分大小寫;
  2. typeof null 返回 object,由於null是Object的一種,表示空引用,即棧內存儲的指向堆中對象的指針爲空;
  3. typeof 能夠判斷function的類型,而且對於非Object類型的數據區分類型比較方便;
  4. 不能區分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

經過以上的代碼段體現出如下特色和弊端:

  1. instanceof 用於檢測Object類型的對象,基本類型的字面量值永遠返回false;
  2. 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中的數據類型與類型轉換

相關文章
相關標籤/搜索