這是我參與8月更文挑戰的第9天,活動詳情查看:8月更文挑戰markdown
ECMAScript變量能夠包含兩種不一樣類型的數據:原始值和引用值。
原始值(primitive value)
就是最簡單的數據,引用值(reference value)
則是由多個值構成的對象。post
在把一個值賦給變量時,JavaScript引擎必須肯定這個值是原始值仍是引用值。spa
Undefined,Null,Boolean,Number,String和Symbol。保存原始值的變量是按值(by value)
訪問的,由於咱們操做的就是存儲在變量中的實際值。3d
引用值是保存在內存中的對象。與其餘語言不一樣,JavaScript不容許直接訪問內存位置,所以也就不能直接操做對象所在的內存空間。在操做對象時,實際上操做的是該對象的引用(reference)
而非實際的對象自己。爲此,保存引用值的變量時按引用(by reference)
訪問的。指針
注意,在不少語言中,字符串是使用對象表示的,所以被認爲是引用類型。ECMAScript打破了這個慣例。code
原始值和引用值的定義方式很相似,都是建立一個變量,而後給它賦一個值。不過,在變量保存了這個值以後,能夠對這個值作什麼,則大有不一樣。對於引用值而言,能夠隨時添加,修改和刪除其屬性和方法。好比,看下面的示例:orm
let person = new Object()
person.name = '何小生'
console.log(person.name) // "何小生"
複製代碼
這裏,首先建立了一個對象,並把它保存在變量person中。而後,給這個對象添加了一個名爲name的屬性,並給這個屬性賦值了一個字符串何小生
.在此以後,就能夠訪問這個新屬性,直到對象被銷燬或屬性被顯式的刪除。對象
原始值不能有屬性,儘管嘗試給原始值添加屬性不會報錯,例如:ip
let name = '何小生'
name.age = 26
console.log(name.age) // undefined
複製代碼
在此,代碼想給字符串name定義一個age屬性,並給該屬性賦值26,緊接着在下一行,屬性不見了。記住,只有引用值能夠動態天價後面可使用的屬性。內存
注意,原始類型的初始化能夠只使用原始字面量形式。若是使用的是new
關鍵字,則JavaScript會建立一個Object
類型的實際,但其行爲相似原始值。下面來看看這兩種初始化方式的差別:
let name1 = '何小生'
let name2 = new String('小何')
name1.age = 26
name2.age = 27
console.log(name1.age) // undefined
console.log(name2.age) // 27
console.log(typeof name1) // string
console.log(typeof name2) // object
複製代碼
除了存儲方式不一樣,原始值和引用值在經過變量複製時也有所不一樣。在經過變量把一個原始值賦值到另外一個變量時,原始值會被複制到新變量的位置。請看下面的例子:
let num1 = 5
const num2 = num1
複製代碼
這裏,num1包含數值5。當把num2初始化爲num1時,num2也會獲得數值5。這個值跟存儲在num1中的5是徹底獨立的,由於它是那個值的副本。
這兩個變量能夠獨立使用,互不干擾。這個過程如圖所示:
在把引用值從一個變量賦給另外一個變量時,存儲在變量中的值也會被複制到新變量所在的位置。區別在於,這裏複製的值其實是一個指針,它指向存儲在堆內存中的對象。操做完成後,兩個變量實際上指向同一個對象,所以一個對象上面的變化會在另外一個對象上反應出來,以下面的例子所示:
let obj1 = new Object()
let obj2 = obj1
obj1.name = '何小生'
console.log(obj2.name) // '何小生' 值已經被複制了
複製代碼
在這個例子中,變量obj1保存了一個新對象的實例。而後,這個值被複制到obj2,此時兩個變量都指向了同一個對象。在給obj1建立屬性name並賦值後,經過obj2也能夠訪問這個屬性,由於它們都指向同一個對象。
如圖,展現了變量與堆內存中對象之間的關係
公衆號:
小何成長
,佛系更文,都是本身曾經踩過的坑或者是學到的東西有興趣的小夥伴歡迎關注我哦,我是:
何小玍。
你們一塊兒進步鴨