JS中‘hello’與new String(‘hello’)引出的問題詳解
定義一個字符串
在工作中我們大概有3種方法去定義一個字符串:
1. var str = 'hello';
2. var str1 = String('hello');
3. var str2 = new String('hello');
(下文直接會帶 以上三個變量....)
這三種方法定義出來的 'hello',都有自己的屬性 例如lengh,有自己的方法例如: indexOf(),在日常工作定義中也沒有感覺到任何的不同。
那是否深入過,
1.這三種方式定義出來的'hello',是否是一樣的呢?
2.為什么基本類型可以直接調(diào)用其對應的方法呢?
這三種方式定義出來的'hello',是否是一樣的呢?
console.log(str === str1) //true console.log(str === str2) //false console.log(str1 === str2) //false
我們可以發(fā)現(xiàn) 最后一種方式定義的 與上面兩種方式定義的 不相等。
???
首先我們知道一個東西 就是:
new 出來的一定是對象。
所以分別 打出三個的類型:
console.log(typeof str) //string console.log(typeof str1) // string console.log(typeof str2) //object
所以這也就是為什么不會嚴格相等的原因。
引出數(shù)據(jù)類型 與 堆棧之間的關(guān)系
嘗試深入理解原因:
我們知道,String,Number,Boolean在JS中是基本類型,基本類型是存儲在棧(stack)內(nèi)存中的,數(shù)據(jù)大小確定,內(nèi)存空間大小可以分配。
而引用類型是存儲在堆(heap)內(nèi)存中的,例如對象, 棧中存在的僅僅是一個堆的指針,這也就是我們?nèi)粘S龅?a = {num:1}, b=a, b.num1 = 2, 那么a.num1 也為2 的原因。因為a,b同時指向同一個地址。
前兩種方式定義出來的是在棧中并且值相等,而第三種方法定義出來的僅僅是棧中的一個指針。
所以這也是為什么 三種方式定義出來的不一樣。
為什么基本類型可以直接調(diào)用其對應的方法呢?
嘗試:
console.log(str.length) // 5 str.say = 'world' console.log(str.say) //undefined console.log(str1.lengh) // 5 str1.say = 'world' console.log(str1.say) //undefined console.log(str2.lengh) // 5 str2.say = 'world' console.log(str.say) //world
引出包裝對象和原始資料類型
我們發(fā)現(xiàn)第一種第二種方式均可訪問lengh屬性,
但是為什么我們并不能自定義一個屬性并進行訪問?
數(shù)字、字符串、布爾三者,在JS中稱為原始的(primitives)資料類型,而 new String(), new Number() 就是包裝對象。
包裝對象也是對象。
這也就是為什么 我們打印 三種類型分別為 : string(原始資料類型) , string(原始資料類型) , object(包裝對象).
我們可以理解 new 出來的 str2 對象有 String 的一系列方法
console.log(str2.indexOf === String.prototype.indexOf) // true
那嘗試一下 第一種第二種方法 是否有同樣的true?
console.log(str.indexOf === String.prototype.indexOf) //true console.log(str1.indexOf === String.prototype.indexOf) //true
但是:
str instanceof String // false str1 instanceof String // false
str 又 不屬于String 卻擁有 String 的方法?????
因為:
這是JS中的設計。
這是JS中的設計。
這是JS中的設計。
原始資料類型的方法與屬性是"借"來的
一個原始的資料類型值,并沒有如對象會有屬性或方法,
原始的資料類型在運算時用的屬性與方法,是向包裝對象"借來"的用的,
所以原始資料類型是可以向 new String() 或者 new Number() 借來所有的方法。但是自己本身卻沒有屬性和方法。
所以這也就是為什么第一種第二種我們無法去自定義屬性卻可以使用對應類型的方法的原因
總結(jié):
1.第一種和第二種方法定義出來的是原始資料類型
并儲存于棧中,
并向包裝對象(new ..())借來方法和屬性.
2.第三種是 包裝對象,
棧中儲存堆指針,
堆中儲存內(nèi)容。
所以這也是發(fā)生一系列看似不正常但是又正常的事情的原因,
哈哈哈哈哈哈哈哈。
當然還有很多的東西,既然牽扯到了堆棧,
那么又不得不了解一下堆棧到底是什么,
有什么區(qū)別等等。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
使用Require.js封裝原生js輪播圖的實現(xiàn)代碼
這篇文章主要介紹了使用Require.js封裝原生js輪播圖的實現(xiàn)代碼,需要的朋友可以參考下2017-06-06js利用clipboardData實現(xiàn)截屏粘貼功能
這篇文章主要為大家詳細介紹了js利用clipboardData實現(xiàn)截屏粘貼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10js通過window.open(url)下載文件并修改文件名
這篇文章主要給大家介紹了關(guān)于js如何通過window.open(url)下載文件并修改文件名的相關(guān)資料,我們知道下載文件是一個非常常見的需求,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-08-08解決js數(shù)據(jù)包含加號+通過ajax傳到后臺時出現(xiàn)連接錯誤
測試過程中發(fā)現(xiàn)js數(shù)據(jù)包含加號+通過ajax傳到后臺時出現(xiàn)連接錯誤,刪除+,鏈接暢通了,果然是這塊問題,對加號進行轉(zhuǎn)義2013-08-08JavaScript中的apply()方法和call()方法使用介紹
我們發(fā)現(xiàn)apply()和call()的真正用武之地是能夠擴充函數(shù)賴以運行的作用域,如果我們想用傳統(tǒng)的方法實現(xiàn)2012-07-07