本文重點在於探討JavaScript變數所包含的兩種不同資料型別的值-基本型別值與參考型別值的差異。在此外稍微帶過ECMAScript和JavaScript的關係。
題為JavaScript變量,但更具體的說法應該是ECMAScript變數。
二十世紀九十年代,Netscape公司和微軟公司推出了兩個不同版本的JavaScript,不利於JavaScript的開發和使用,促使歐洲電腦製造商協會(ECMA, European Computer Manufacturers Association)著手處理JavaScript的標準化問題,從而完成了著名的ECMA-262——定義了一種名為ECMAScript的新腳本語言的標準。
一個完整的JavaScript實作包含ECMAScript,文件物件模型(DOM,Document Object Model),以及瀏覽器物件模型(BOM,Browser Object Model)。 ECMAScript作為JavaScript的核心以及實現的基礎,是ECMA-262標準規定的在語法、類型、語句、關鍵字、保留字、操作符和對象這幾個方面內容的語言的描述。
ECMA-262標準規定的ECMAScript變數是鬆散類型的,可以用來保存任何類型的數據,所以不同類型初始化變數的操作可以放在一條語句中執行,如下列程式碼是合法的。
var message = "hello", //string age = 20, //number3 found = false; //boolean
用 var 運算子定義的變數將成為定義該變數的作用域中的局部變量,而退出該作用域後變數會立即被銷毀。例如在函數內定義一個變量,當函數被呼叫的時候,該變量即被創建,但在函數退出後,該變量將無法再被繼續訪問。
ECMAScript中有6種資料型別(也只有6種資料型別(也只有6中,ECMAScript不支援任何建立自訂類型的機制)。
其中基本資料型別包括5種-underfined、null、boolean、number、string,這5種基本資料型別按值訪問,其值屬於文章開頭提到的基本類型值,是簡單的資料段,可以操作保存在變數中的實際的值。
第6種為複雜資料型別-object,本質上是由一組無序的名-值對組成的,屬於引用型別值,是保存在記憶體中的對象。 JavaScript不允許直接操作物件的記憶體空間,在操作物件時實際上是在操作物件的引用而不是實際的物件。
雖然定義變數時不需要規定其為何種資料型別,但基本型別和參考型別的值可以執行的動作還是大相逕庭。
屬性的新增
對於引用型別的值,可以為其屬性和方法進行新增、變更和刪除,如下列程式碼:
var obj = new object(); //创建对象并保存在obj中 obj.name = "Marry"; //添加名为name的属性,赋予字符串值“Marry” alert(obj.name); //弹出"Marry"
如果obj物件不被銷毀或name屬性不被刪除,這個屬性將一直存在。
再看基本類型值:
var name = "Marry"; //创建字符串 name.age = 20; //添加名为age的属性,赋予number值20 alert(name.age); //弹出"underfined"
name字串被加入了一個age屬性,為其賦值20,但下次訪問時這個屬性就不見了。
這說明只能動態地新增屬性給引用型別值。
複製變數值
## 從變數a向變數b複製基本型別的值,會在變數b物件上建立一個新值,將該值複製到給變數a指派的位置上,獨立保存。這兩個變數參與的任何操作都不會互相影響。
若从变量c向变量d复制引用类型的值,同样会将存储在变量d对象中的值复制一份放到为变量c分配的空间中,但这个值的副本实际是一个指针,与变量d指向堆内存中的同一个对象。两个变量实际引用同一个对象,改变其中一个变量,将影响另一个变量。
具体区别见如下例子:
//基本类型值 var num1 = 5;var num2 = num1; num2 = num2 + 5; alert(num1); //5alert(num2); //10/ /引用类型值 var obj1 = new object();var obj2 = obj1; obj1.name = "Marry"; alert(obj2.name); //"Marry"
函数传参
ECMAScript中所有函数的参数都是按值传递的,即将函数外部的值复制给函数内部的参数。鉴于基本类型值与引用类型值复制变量的不同,其函数传参的效果也不同。
在向参数传递基本类型值时,被传递的参数被赋给一个局部变量,函数内部参数的变化不影响函数外部的变量;向参数传递引用类型值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化将会反映在函数的外部。如下列例子:
//传递基本类型值function addnum(num) { num += 10; return num; }var num1 = 5;var num2 = addnum(num1); alert(num1); //5,无变化alert(num2); //15//传递引用类型值 function setage(obj) { obj.age = 20; }var obj1 = new object(); setage(obj1) alert(obj1.age); //20
在局部作用域中修改的对象反映在全局作用域中,很多人会以为这是按引用传递。但函数对象确实都是按值传递,见下列例子:
function setage(obj) { obj.age = 20; obj = new object(); obj.age = 30; }var obj1 = new object(); setage(obj1) alert(obj1.age); //20
此例中在函数内部为obj重新定义了一个对象,且为其age属性重新赋值,但这一变化并未反映在函数外部,说明obj1 并不是按引用传递的。实际函数内重新定义的对象为局部对象,在退出函数后就会被立即销毁。
检测类型
基本类型值可以通过typeof检测,但typeof检测引用类型时只能返回object。所以为了知道某个值是什么类型的对象,ECMAScript提供了instanceof操作符,语法如下:
result = variable instanceof constructor
如果变量是引用类型的实例,instanceof操作符就会返回true。
以上是有關JavaScript變數相關問題詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!