對象是組成JavaScript的基本單元,在JS中,一切東東其實都是對象,而且功能非常強大,它不僅風格獨特,功能也與眾不同。
一、引用(reference)
引用的概念是JS的基礎之一,它是指向對象實際位置的指標。見下面的例子:
var items = new Array("abc","def","hig");//建立此數組的引用var Ref = items;items.push("klm");alert(Ref.lenth); //此處應該顯示4
但是,如果是字串,就會出現不同的情況,見下面的代碼:
var items = "abc";var Ref = items;items += "def"; //這裡建立了一個新對象,而非原對象的修改。
現在Ref與items指向的是不同的對象。
二、函數重載
JS的每個函數都有一個變數argument,它是接收所有參數的偽數組。為什麼是“偽”,因為你不能修改它,但它有length屬性。我們看看下面的例子:
function myFun(num1,num2){if(arguments.length == 2) { alert("我有兩個參數"); }if(arguments.length == 1) { alert("我有一個參數"); }}
接下來,我們調用函數myFun("abc"); myFun("abc","def");看看有什麼不同,最重要的是,這本來就是函數重載嘛:)
三、範圍
在JavaScript裡,範圍是由函數劃分的,而不是由塊(while,if,for)劃分的。這樣在理解有些代碼時,可能會帶來一些麻煩。為了對細節進行說明,我們看下面的例子:
var temp="oldTemp" //全域變數if(true){var temp = "newTemp" //這裡還在全域中}alert(temp == "newTemp") //發現相等
但是如果我們在一個函數中聲明並改變temp變數,效果則完全不同,見例子:
var temp="oldTemp" ; //全域變數function test(){var temp = "newTemp";}test();alert(temp == "newTemp") ; //發現不相等
在JS中,全域變數是window對象的一個屬性,在上面的例子中,全域變數temp == window.temp,還有需要注意的是:如果某一個變數缺乏聲明,就自動變為全域變數,雖然很可能它只在某個函數中使用。
四、閉包
閉包意味著內層的函數可以引用包圍它的函數內的變數,即使外層函數已經終止。見下面的例子:
function AddNum(num1){return function (num2){ return num1 + num2;}}var temp = AddNum(4); //傳入第一個參數,然後AddNum消失var temp2 = temp(5); //傳入第二個參數,然後相加,返回9alert(temp2);
這個例子很好體現了閉包的概念,是一種特殊情況,平時當然不這麼用。
五、內容物件
內容物件通過this變數進行體現,這個變數永遠指向當前代碼所處的對象中。見下面的代碼:
var obj ={yes:function(){ this.val = true;},no:function(){ this.val = false;}}alert(obj.val == null); //這裡我們發現對象obj沒有val屬性obj.yes(); //執行yes函數,obj有了val屬性alert(obj.val == true);window.no = obj.no //把obj的no函數傳給window對象window.no();alert(obj.val == true) ; //發現沒有變化alert(window.val == false) //window裡的val變為false;
這裡不太好理解,幸運的是,JS為我們提供了call方法。見下面的例子:
function changeColor(color){this.style.color = color;}changeColor("Red"); //這裡不行,因為window對象沒有style屬性var temp = document.getElementById("temp");changeColor.call(temp,"White"); //這裡注意call的用法
call方法將內容物件設定為第一個參數,並將其他參數作為原函數的參數。
六、對象
到這裡我們才進入正題,但有了前面的概念,這也塊內容其實也不是很多。我們直接看例子:
var obj = new Object(); //建立一個對象objobj.val = 5; //建立屬性obj,並為其賦值obj.click = function() //建立函數{alert("我被單擊了");}
上面的代碼與下段代碼等價:
var obj = {val : 5,click: function(){alert("我被單擊了");}}
與其他物件導向語言不同的是,JS並沒有Class的概念,在其他語言中,我們基本都需要執行個體化某個具體類的執行個體,但JS裡卻不同,它的做法是:任何函數都可以被執行個體化為一個對象。我們首先建立一個簡單的對象:
function User(name){this.name = name;}var temp = new User("張三");alert(temp.name);
如果上面的對象User只作為函數使用呢?
User("只作為函數使用");alert(window.name);
this的上下文變成了window對象。
七、對象的方法
公用方法在對象的上下文中是終端使用者可以接觸到的。這裡我們需要理解prototype(原型)屬性。見下面的代碼:
function User(name,age){this.name = name;this.age = age;}User.prototype.getName = function(){ return this.name};var user = new User("張三",25);alert(user.getName());
我們也可以動態建立公用方法,見下面的代碼:
function User(name,age){this.name = name;this.age = age;this.getName = function(){ return this.name};}var user = new User("張三",25);alert(user.getName());
動態產生的方法不是在代碼第一次編譯時間就已經產生,這個技巧被利用prototype開銷要大,但也更強大、更靈活。