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.爲何基本類型能夠直接調用其對應的方法呢?
複製代碼

這三種方式定義出來的'hello',是不是同樣的呢?

console.log(str === str1) //true
console.log(str === str2) //false
console.log(str1 === str2) //false

咱們能夠發現 最後一種方式定義的 與上面兩種方式定義的 不相等。
???
首先咱們知道一個東西 就是: 
new 出來的必定是對象。

因此分別 打出三個的類型:
console.log(typeof str) //string
console.log(typeof str1) // string
console.log(typeof str2) //object

因此這也就是爲何不會嚴格相等的緣由。
複製代碼

引出數據類型 與 堆棧之間的關係

嘗試深刻理解緣由:

咱們知道,String,Number,Boolean在JS中是基本類型,
基本類型是存儲在棧(stack)內存中的,數據大小肯定,內存空間大小能夠分配。

而引用類型是存儲在堆(heap)內存中的,例如對象, 棧中存在的僅僅是一個堆的指針,
這也就是咱們平常遇到 a = {num:1}, b=a, b.num1 = 2, 那麼a.num1 也爲2 的緣由。由於a,b同時指向同一個地址。

前兩種方式定義出來的是在棧中而且值相等,而第三種方法定義出來的僅僅是棧中的一個指針。
因此這也是爲何 三種方式定義出來的不同。
複製代碼

爲何基本類型能夠直接調用其對應的方法呢?

嘗試:
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
複製代碼

引出包裝對象和原始資料類型

咱們發現第一種第二種方式都可訪問lengh屬性,
可是爲何咱們並不能自定義一個屬性並進行訪問?

數字、字符串、布爾三者,在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() 借來全部的方法。可是本身自己卻沒有屬性和方法。

因此這也就是爲何第一種第二種咱們沒法去自定義屬性卻可使用對應類型的方法的緣由
複製代碼

總結:

1.第一種和第二種方法定義出來的是原始資料類型
並儲存於棧中, 
並向包裝對象(new ..())借來方法和屬性.

2.第三種是 包裝對象,
棧中儲存堆指針,
堆中儲存內容。

因此這也是發生一系列看似不正常可是又正常的事情的緣由,
哈哈哈哈哈哈哈哈。
固然還有不少的東西,既然牽扯到了堆棧,
那麼又不得不瞭解一下堆棧究竟是什麼,
有什麼區別等等。
複製代碼
相關文章
相關標籤/搜索