數據類型與對象

Author:eret9616javascript


不知不覺已經到了7月了,還有5個月就能過年了,加油鴨...
java

最近我所在的項目中開始引入TypeScript,其中涉及到了強類型的一些概念,今天咱們就來一塊兒梳理一下數據類型、對象的概念,

git

正文:github

當你天天嚷嚷着面向對象編程的時候,你知道什麼是對象嘛
雖然你可能沒有對象,可是你能夠學習什麼是對象編程


C語言中的對象

在C語言中,對象指結構體的實例
數組

// 聲明一個結構體
struct student{
   Int a;  //4byte
   char b; // 1byte
   char c; // 1byete
   short d; // 2byte
}
複製代碼

這句話聲明瞭student結構體這種數據類型,

告訴C編譯器student結構體將佔用內存8byte大小,瀏覽器


當寫下並執行下面這句話時
struct student s1 = {12,'a','b',2} 就進行了實例化的操做,
而後會在內存棧空間分配8個byte大小,並填充上面你定義的數據,bash


若是聲明的結構體中有函數指針,那麼實例化的對象中就能調用方法了。

數據類型的本質

數據類型的本質是固定長度大小內存塊的別名。數據結構

各類數據類型,在編譯器眼裏只是別名,

int 是4字節內存塊的別名,char是1字節內存塊的別名, 當你聲明瞭一種結構體,你就是在告訴編譯器這個名字是多少長度內存塊的別名。在C語言中,經過sizeof操做符,能夠查看數據類型所佔用的空間大小,sizeof(struct Student)就能夠拿剛剛聲明的結構體所佔用的字節8, 拿到字節後能夠在堆空間去malloc(sizeof(struct Student)),分配空間後,能夠賦值並完成在堆空間上數據的建立。

app

對象

明確了數據類型的意義後,就能夠給出對象的定義了: 對象是指自定義長度、結構的數據類型的實例,對象是區別於基本數據類型的實例的。 須要明白的是, 對象和他在堆空間仍是在棧空間上沒有關係,剛纔的例子裏一開始在棧空間建立了對象,後面也提到用sizeof獲取大小並在堆空間建立對象。

數組是對象嗎

在C語言中初始化數組不涉及到結構體,由於數組內部結構是固定的,因此數組不是對象,數組是連續的每一個單元大小固定的結構固定的一種數據結構,它不是對象。

可是JavaScript中的數組是對象,Array繼承於Object,而且能夠向上添加方法

// 數組添加方法
var a = [1,2,3]
a.b = function(){...}
複製代碼

簡單的說,JS的數組並非C中的真正的數組,在內存中存儲的方式不是C數組那麼簡單的結構,他是複雜的數據結構,由於上面可以調用方法,還能自動append長度,類比List,Stack,Map,Set這些數據結構,由於內部能夠調用方法,他們在內存中的實際存儲方式都是結構體方式,結構體內部有函數指針。

堆空間與棧空間

操做系統進程內存模型分爲不一樣的區域,堆和棧是其中的兩個區域,棧的空間相比堆要小不少,遇到佔用大空間的數據(如自定義的對象)通常要放到堆上存儲。

隨着時間推移,到了C++時代,C++中出現了類的概念,類其實就是結構體。只是加了一些特性的結構體,因此, 在聲明類時你能夠定義它的構造函數(C語言中沒有構造函數的概念)

// 類
class Student{
   Int a;  //4byte  
   char b; // 1byte
   char c; // 1byete
   short d; // 2byte
   // 構造函數
public:Student(){
     cout << 「Hello」 << endl; 
}
}
複製代碼

構造函數是指當這個類被實例化初始成一個對象時會被執行的函數,那想一下它的實現…其實就是帶了函數指針的結構體,在被實例化的時候C++編譯器會去執行這個函數指針指向的你定義的構造函數。

new

C++引入的new操做符至關於malloc && 執行構造函數。當new一個類的時候, 就是在堆空間進行malloc,而後去執行這個類的構造函數。JavaScript中的new不只僅這麼簡單,但瞭解了最原始的new,你就明白了new究竟是在作什麼。

高級語言

JavaScript的解釋器引擎由C/C++編寫,不一樣瀏覽器運行着不一樣廠家編寫的引擎,只是由於這些引擎都遵照着ECMA規範,因此看起來好像跑起來都同樣。

在JS中,數據類型被分爲 原語類型(primitive )和對象(Object)

原語類型包含Boolean,Null,Undefined,Number,BigInt,String,Symbol

JavaScript暴露的內容不涉及手動在堆與棧分配內存,

也沒有sizeof方法來判斷某個數據類型的大小,

但咱們能夠在語言規範中一窺這些基本數據類型的定義


在ECMA規範中:

Number: primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value
雙精度64位浮點

String: primitive value that is a finite ordered sequence of zero or more 16-bit unsigned integer
字符串中每一個值都是16位無符號整數

......


所謂的原語類型,是基於語言規範定義的,String類型雖然是原語類型,但倒是不定長的,從規範來看他就是一個數組,數組中每一個元素都是16位無符號整數,因此當你初始化一個字符串的時候,他的長度是基於你字符串內容的。但能夠確定的是,它的結構是不能被自定義的,數組中的每一個元素都是依照這一規範的,它不能被添加方法。
var a = 'asdf'
a.b = function(){...}
a.b // undefined
複製代碼

原語類型調用方法

在JavaScript中,原語數據類型是沒有方法的,

當你嘗試對原語數據類型進行操做時,引擎會進行"裝箱":

var a = 1  
var b = a.toString()
複製代碼

a是一個基本數據類型,不是對象,不該該有方法, 但當你執行a.toString() 或嘗試調用方法時,引擎會建立一個對象

一、調用Number類,建立一個實例
二、在實例上調用該方法
三、銷燬這個實例

這個過程也能夠相似用代碼來表示:

var _a = new Number(1)  
var b = _a.toString()   
_a = null   
複製代碼

參考資料:

developer.mozilla.org/en-US/docs/…
www.ecma-international.org/ecma-262/5.…
www.github.com/getify/You-…
stackoverflow.com/questions/3…

相關文章
相關標籤/搜索