js基本數(shù)據(jù)類型和對象

5種基本數(shù)據(jù)類型:String, Boolean, Number, null, undefined

2種引用數(shù)據(jù)類型: Array, Object

es6新增兩種引用類型: Set, Map


首先只有對象才可以擁有屬性, 以及使用"."操作符。

假如我們要使用的字符串的split方法,可以用String.prototype.split.call(),或者"".split.call()。

有天突然腦子抽筋想了下String到底是什么,首先String是個函數(shù),可以使用

let str = new String();創(chuàng)建一個字符串,但是想想也可以使用String.prototype,意味著String是個對象,

也就是說函數(shù)是個對象咯,再想想函數(shù)是有name屬性的,也可以自定義屬性,貌似說的通,

再進一步想,也就是說new String()的時候其實是在new { ... }。//new { ... } 做了什么?

我使用控制臺把String輸出,發(fā)現(xiàn)確實是個對象,也說明函數(shù)其實是個對象,所以Array,Object,Number,Boolean(Set,Map)都是對象, 雖然用typeof String會得到function,但它的本質(zhì)是個對象。

查看String對象后發(fā)現(xiàn)

String.__proto__ === Function.prototype // true

猜想:難道String是Function的一個實例化對象

接著運行

String instanceof Function // true

表示一臉蒙蔽,然后試了Number,Boolean,Array, Object等發(fā)現(xiàn)都是這樣。

打印Function發(fā)現(xiàn)它還有個Function.__proto__ === Function.prototype,而且 Function.prototype === Object.__proto__ //true

就神奇的出現(xiàn)了

Function instanceof Object //true

Object instanceof Function //true

之后查了下instanceof是根據(jù)什么來判斷對象A是否是對象B的實例,結(jié)果是:如果A的__proto__鏈上存在B的prototype,就返回true否則false

然后重新審視了整個__proto__鏈, 畫出了下圖。


類型對象關(guān)系圖

得出結(jié)論:

1. 所有函數(shù)本質(zhì)都是對象

2. 以上所有的對象的__proto__屬性都指向Function.prototype(所有的函數(shù)也是這樣的)。

3. 除Object外的所有對象的prototype內(nèi)的__proto__屬性都指向Object.prototype。

4. Object.prototype相當于基類的存在,定義了toString和valueOf等方法。

結(jié)合上圖和instanceof的原理,就能夠合理的解釋

Function instanceof Object //true

Object instanceof Function //true

并且:

String instanceof Function //true;

String instanceof Object //true

但是我不理解的是:

1. js為什么要這樣去設(shè)計。

2. String是如何獲取到定義在String.prototype上的split方法的。(難不成prototype上的方法是String對象自定義后再賦值的)


按照以上結(jié)論,可以想象出一下代碼的運行步驟

let str = new String("hello world");

str.split(" ");

在這里str是一個Sting對象;

而同樣的也可以這樣寫:

let words = "hello world";

words.split(" ");

難道這個words也是個對象嗎,我試著給這個words自定義屬性:words.name = "sss";

打印出來的結(jié)果為undefined,所以這里的words不是個對象,只是個基本數(shù)據(jù)類型,那為什么它能夠調(diào)用split方法呢。

查閱相關(guān)文檔后得知,words是基本數(shù)據(jù)類型,被存放在棧中,是不存在屬性的,當我們嘗試去調(diào)用words.split時,會先創(chuàng)建一個字符串

let temp = new String(words);然后調(diào)用temp.split(" "),并返回結(jié)果,最后再將temp銷毀(temp = null)。

那么以new String()和字面量的形式聲明一個字符串,有什么區(qū)別呢,它們的使用方式都一樣,只是創(chuàng)建的方式不一樣。

補充一下,基本數(shù)據(jù)類型是存放在棧里的,引用數(shù)據(jù)類型是存放在堆里的,這也是他們的區(qū)別之一,我真正想知道的是為什么要這樣設(shè)計,我們平常基本不使用new String(),而且也不推薦使用,因為更耗內(nèi)存和性能,那它存在的意義何在。

思考:

1. []和new Array的區(qū)別在哪?

2. function show() {}和 let show? = new Function() {}的區(qū)別在哪?

3. let n = 2和 let n = new Number(2)的區(qū)別在哪?如果n = new Number(2); n +2 會是多少,為什么,注意這里的n是個對象,也就是對象+2。

4. new String()發(fā)生了什么。

最后不推薦在實際開發(fā)中使用__proto__屬性,該屬性是供瀏覽器使用的一個私有屬性,如果要獲取一個對象的__proto__,應(yīng)該使用Object.getPrototypeOf()方法。

我不理解的問題在我得出正確的解釋后會進行補充或者更正。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容