ECMAScript 的變量是鬆散類型的,也就是說能夠保存任何類型的數據。數據的類型分爲簡單數據類型和複雜數據類型。簡單數據類型有: Undefined、Null、Boolean、Number和 String;複雜數據類型只有一種,就是Object。在將一個值賦值給變量時,解析器會肯定值的類型。若是是簡單類型,直接保存在變量中,若是是複雜類型,則把值保存在內存中,而把值的引用保存在變量中。也就是說變量的值有兩種:簡單的數據類型的值或者複雜數據類型的引用。所以,在操做變量時,就會有所不一樣。數組
一、添加屬性瀏覽器
變量的值是複雜數據類型時,能夠簡單的爲其添加屬性。這個很容易理解,而當變量的值是某些簡單的數據類型時,爲其添加屬性也不會報錯,但以後卻不能訪問,以下:框架
var person= "xiaoming"; name.age = 27; alert(name.age); //undefined
這是由於JavaScript引擎在處理添加屬性的代碼時,會在內部臨時建立一個對應包裝類型(這裏是String類型)的臨時對象, 並把對基本類型的操做代理到對這個臨時對象身上,但在操做完成以後,臨時對象就扔掉了,下次訪問時,從新創建新的臨時對象,添加的屬性並不會 保存。有時,在代碼中直接調用基本數據類型的方法的方法也是一樣的道理。所以,只能給複雜數據類型的值添加屬性。函數
二、賦值變量的值spa
從一個變量向另外一個變量複製值時,會爲新的變量分配位置,而後把變量的值複製到該位置上。無論變量的中保存的是基本數據類型的值,仍是複雜數據類型的引用,都是直接把變量中保存的值直接賦值並保存到新的位置上面。prototype
簡單的數據類型很好理解,複雜的數據類型能夠參照下圖:
代理
變量obj2複製的是obj1中保存的對象的引用,複製以後,obj1和obj2中分別保存一個指向該對象的引用。code
三、傳遞參數對象
ECMAScript 中全部函數的參數都是按值傳遞的。也就是說在傳遞參數時,實際上就是把變量中保存的值複製了一遍,保存在對應的參數中,從而變成了函數內部的一個變量。這時,須要注意的一點時,對於簡單的數據類型,新的變量(參數)和外部的變量已經沒有聯繫了。而對於複雜數據類型,由於兩個變量中保存的都是對象的引用,所以兩個變量仍是僅僅聯繫在一塊兒的,以下:blog
var a = 3; var o = { name:'xiaoming' }; function fn(obj, num){ num += 10; o.name = 'hh'; return num; } var res = fn(); alert(res); //13 alert(a); //3 alert(o.name); //'hh'
四、檢測類型
正如開頭說的變量是鬆散的,爲了確保代碼能夠正確的執行,不少時候都須要檢測變量值的類型。變量的值是簡單的數據類型時(null除外),只須要使用typeof操做符,就能夠很簡單的檢測出來。但變量的值是複雜數據類型的引用時,就有點麻煩了,使用typeof始終只會返回‘object’。若是知識簡單的檢測,可使用 instanceof 操做符。使用以下:
res = obj instanceof constructor
只要變量是給定複雜數據類型的實例,那麼instanceof 操做符就會返回 true。須要說的一點是, 全部複雜數據類型的值都是 Object 的實例,使用這個操做符檢測是否是Object構造函數的實例時,都會返回true。
使用這種方式檢測在大多數狀況下都是沒有問題的,但當頁面的中存在嵌套的框架或者在一些特殊的瀏覽器中就會出現問題。例如,在一個frame中定義了一個數組arr,而在最外層的window環境中檢測,就會返回false。爲了確保檢測結果的正確,可使用Object原聲的toString方法,對於任何的複雜數據類型,這個方法都會返回「 [object NativeConstructorName]」格式的字符串,例如:
Object.prototype.toString.call([]) //"[object Array]"