天天看點

《HTML5+JavaScript動畫基礎》——2.4 JavaScript對象

本節書摘來自異步社群《html5+javascript動畫基礎》一書中的第2章,第2.4節,作者:【美】billy lamberta , keith peters著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

本書的重心在于使用javascript建立動畫所需的各種原理和公式而不是具體的程式設計技巧。是以,本書中不會建立龐大的架構庫或者複雜的資料結構,而是盡可能保持代碼的簡潔。

你可以将在本書中學到的動畫概念納入更加進階的javascript項目中,不過,本書的目的不是交給你一份預先建構好的代碼供你複制和粘貼,而是試圖讓你了解每一種動畫的工作原理。

由于本書采用javascript編寫示例,是以你需要了解該語言的一些重要概念以便于了解示例代碼。javascript中最重要的東西就是對象和函數(一種特殊的對象),讓我們從它們入手吧。

2.4.1 基礎對象

javascript被設計成一個簡單的面向對象系統。對象是一個包含若幹屬性的資料結構。這些屬性可以是變量、函數或其他對象。當給一個函數賦給一個屬性時,它稱為一個對象的方法。浏覽器中預定義了很多對象,不過開發者也可以建立自定義的對象。例如,可以像下面這樣建立一個空對象并将它賦給一個變量供将來引用:

<code>var obja = {};</code>

這裡建立了一個不具備任何屬性的對象并将其儲存到變量obja中。由于javascript對象預設情況下可以在任何時間修改,是以可以像下面這樣為它添加一個新的屬性:

<code>obja.name = "my object a";</code>

以上代碼在obja對象中建立了一個名為name的新屬性并把一個字元串值"my object a"賦予它。總是可以通過obja.name的方式通路對象的屬性值。也可以如下在聲明一個新對象的時候就為之建立屬性:

這裡建立一個新對象objb,它包含兩個屬性,一個包含字元串的name屬性以及一個儲存函數的hello屬性。由于在javascript中函數也是對象,是以可以像對待其他值一樣将其傳來傳去,也可以将其賦給某個變量。上面這個例子中的方法接收一個字元串參數,并向浏覽器的調試控制台輸出一條消息:

<code>objb.hello("gentle reader"); //prints: "hello, gentle reader"</code>

2.4.2 建立一類新對象

可以聲明對象使其包含所需的屬性,不過如果你想要建立多個包含相同屬性定義的對象,該怎麼辦呢?當然可以逐一建立它們,不過更加高效的方式是使用構造函數。構造函數是一種特别的函數,它會根據配置設定給它的屬性建立新的對象。在定義好該函數後,可以使用new指令調用構造函數以建立新的對象。為了區分構造函數與普通函數,約定構造函數的名稱首字母大寫:

留意,在構造函數中用于添加屬性的特殊對象this。該對象将作為構造函數的傳回值。在構造函數中聲明的任何變量如果沒有關聯到this對象,則無法在構造函數外直接通路。

2.4.3 原型

使用構造函數建立對象執行個體是在基于類的語言中的習慣做法。事實上,當你檢視javascript檔案中對類的介紹時,你會發現它通常所指的就是構造函數。不過該術語有時候會讓人忽略了javascript實際上是基于原型的語言。

當在javascript中建立新對象執行個體時,實際上建立新對象,該對象從其構造函數對象(即其原型對象)中繼承它的所有屬性。可以通過構造函數的prototype屬性直接通路這些對象。賦予原型的任何屬性都将被派生自該類型的所有對象所共享。以下代碼基于之前的示例構造函數:

這裡為構造函數的原型對象添加了hello函數,這樣做之後,把該函數同時添加到之前聲明的obja對象以及新建立的objb對象中。

本書中建立了一些被很多示例共享的類(一個構造函數與prototype屬性)。通常情況下,把這些類放入一個獨立的檔案然後導入html5檔案中。

2.4.4 函數風格

javascript的一大優勢在于函數是作為一等公民而存在的對象。這意味着,可以将函數賦予變量,将它們傳來傳去并将它們作為其他函數的參數,而這是很多程式設計語言所不具備的強大功能與概念。盡管它蘊含的内容可以演變得相當複雜,但是這個概念卻非常簡單明了,并且在本書大量運用。如果你能夠很好地掌握這一概念,你将成為一個成功的javascript程式員。

你已經在之前建立一個動畫循環的時候使用過函數參數,setinterval與requestanimationframe都有使用回調函數作為它們的參數。除此之外,還可以用函數簡化代碼。例如,下面用一個for循環周遊一個數組中的值。建立計數器變量i,它在每次循環中遞增并用于通路數組的值。聲明一個包含三個元素的數組并将它們輪流輸出到控制台。

也可以用函數實作上述功能。每個javascript數組對象都有一個名為foreach的方法,該方法接收一個函數作為參數。foreach方法會周遊所有的數組元素,将每個元素作為第一個參數傳遞給使用者定義的函數,同時該元素在數組中的索引位置會作為第二個可選參數傳入。以下是采用該方法實作之前那個例子的代碼:

以上代碼段跟之前的示例實作了相同的功能(将數組中的每個元素輸出到控制台),不過結構卻大不相同。這麼做有以下幾點好處。首先,不用為了周遊聲明任何臨時變量,尤其是這些變量在這段代碼執行完後就沒用了。不過更重要的在于,這種風格的代碼使得你能夠寫出函數層面的代碼。這意味着,可以通過檢視作為參數傳入的函數與函數接收的參數了解代碼如何工作,而無須擔心循環的狀态或依賴的變量是否設定正确。這有利于調試,因為當發生錯誤時,可以通過一層層深入棧跟蹤上的函數調用來定位發生錯誤的代碼。

由于執行函數需要一些額外的計算,采用函數實作周遊的一個缺點就是其速度會慢于for循環。當開發者在編寫程式時,經常需要同時考慮代碼的可讀性與執行速度,而這隻能交由測試決定。通常情況,你應該盡可能編寫簡單易懂的程式,而讓浏覽器廠商去關心如何讓代碼執行得更快。

在本書中根據速度和簡潔性的不同需求,兩種周遊方式都有用到。使用javascript與dom更常見也更核心的用法也需要将函數作為事件處理程式傳入。我們會在下一節介紹使用者互動時了解這是如何工作的。

繼續閱讀