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屬性的困乒,也可以自定義屬性寂屏,貌似說的通,
再進(jìn)一步想,也就是說new String()的時候其實(shí)是在new { ... }迁霎。//new { ... } 做了什么吱抚?
我使用控制臺把String輸出,發(fā)現(xiàn)確實(shí)是個對象考廉,也說明函數(shù)其實(shí)是個對象秘豹,所以Array,Object昌粤,Number既绕,Boolean(Set,Map)都是對象涮坐, 雖然用typeof String會得到function岸更,但它的本質(zhì)是個對象。
查看String對象后發(fā)現(xiàn)
String.__proto__ === Function.prototype // true
猜想:難道String是Function的一個實(shí)例化對象
接著運(yùn)行
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的實(shí)例,結(jié)果是:如果A的__proto__鏈上存在B的prototype非区,就返回true否則false
然后重新審視了整個__proto__鏈瓜挽, 畫出了下圖。
得出結(jié)論:
1. 所有函數(shù)本質(zhì)都是對象
2. 以上所有的對象的__proto__屬性都指向Function.prototype(所有的函數(shù)也是這樣的)征绸。
3. 除Object外的所有對象的prototype內(nèi)的__proto__屬性都指向Object.prototype久橙。
4. Object.prototype相當(dāng)于基類的存在,定義了toString和valueOf等方法管怠。
結(jié)合上圖和instanceof的原理淆衷,就能夠合理的解釋
Function instanceof Object //true
Object instanceof Function //true
并且:
String instanceof Function //true;
String instanceof Object //true
但是我不理解的是:
1. js為什么要這樣去設(shè)計(jì)。
2. String是如何獲取到定義在String.prototype上的split方法的渤弛。(難不成prototype上的方法是String對象自定義后再賦值的)
按照以上結(jié)論祝拯,可以想象出一下代碼的運(yùn)行步驟
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ù)類型籽前,被存放在棧中亭珍,是不存在屬性的腊瑟,當(dāng)我們嘗試去調(diào)用words.split時,會先創(chuàng)建一個字符串
let temp = new String(words);然后調(diào)用temp.split(" ")块蚌,并返回結(jié)果,最后再將temp銷毀(temp = null)膘格。
那么以new String()和字面量的形式聲明一個字符串峭范,有什么區(qū)別呢,它們的使用方式都一樣瘪贱,只是創(chuàng)建的方式不一樣纱控。
補(bǔ)充一下,基本數(shù)據(jù)類型是存放在棧里的菜秦,引用數(shù)據(jù)類型是存放在堆里的甜害,這也是他們的區(qū)別之一,我真正想知道的是為什么要這樣設(shè)計(jì)球昨,我們平扯辏基本不使用new String(),而且也不推薦使用主慰,因?yàn)楦膬?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ā)生了什么涎嚼。
最后不推薦在實(shí)際開發(fā)中使用__proto__屬性,該屬性是供瀏覽器使用的一個私有屬性挑秉,如果要獲取一個對象的__proto__铸抑,應(yīng)該使用Object.getPrototypeOf()方法。
我不理解的問題在我得出正確的解釋后會進(jìn)行補(bǔ)充或者更正衷模。