運用prototype屬性,達成物件導向的繼承功能。
重構圖片輪撥的slider功能,使其程式結構更完整。

運用prototype屬性,達成物件導向的繼承功能。 重構圖片輪撥的slider功能,使其程式結構更完整。


js結構化寫法

上一章中,我們已經完成了slider來捲動圖片的功能,這一章我們我使其寫法更加結構化,以便讓日後的程式碼更易擴充新功能

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.00.06.71.jpg

介紹javascript的prototype的一個學習網站->scriptjunkie

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.01.11.92.jpg

另 一個為Modulus的學習網站

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.01.42.71.jpg

js的資料型態-function等於object

我們至今都已有一些寫javascript的經驗了,我們都很熟悉於宣告一個陣列,如:var arr=[1,2,3],而如要新增一個陣列物件可用其push()的方法。但是當你使用push()的時後,你有沒有想過,這個push()是怎樣來的?javascript並沒有class(類別物件),那樣如何建立此方法psuh()?

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.02.40.71.jpg

因此,javasctip一定有其它的型態可達成class(類別)的功能,我們開始逐漸偵測各種變數的型態。首先,先測試Array的態態,輸入dir(Array)來判斷其型態為何,結果Array的型態為function

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.02.52.88.jpg

也可用typeof的方式測試變數型態,一樣測出來為function

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.02.57.71.jpg

這次換測試Object的型態,結果也一樣是function

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.03.01.29.jpg

function竟然包含了屬性和方法!這代表了在javascript中的function型態,等同於其它程式語言的class

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.03.16.71.jpg

prototype屬性介紹

解說因為prototype屬性的原因,任何由Array所產生的物件(如:arr = new Array()),都可使用包含在ptototype的方法,但是只有呼叫new array()產生實例時,才能被使用,才會佔用到記憶體

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.04.10.71.jpg

類別產生實例(instance)之後,this的不同

尚未產生新的實例(instance)以前,this代表為window

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.04.39.71.jpg

new Slider();//用來產生slider實例

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.04.54.71.jpg

運行結果,console出Slider物件內的this為Slider//產生實例後this就不再是window了

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.05.00.71.jpg

類別產生多個實例(instance)之後,重覆的屬性和方法(method)

在此Slider物件內,新增自訂的屬性direction和方法move(),並透過Slider.move()來執行

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.05.46.50.jpg

運行結果,成功執行自訂的方法,console出moving字串

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.05.48.17.jpg

產生2個Slider()的實例,slider和slider2,並用console.dir()觀察其內部的變數

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.06.06.71.jpg

運行結果,可看到2個實例化的slider,都擁有各自獨立的屬性和方法。但我們不需要複製出這麼多的方法(move()只要一個就夠了,沒必要個自獨立為一個)。所以要如何利用物件導向的方法,來做到在其父層宣告方法後,在讓子層去繼承就好了呢?

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.06.10.71.jpg

運用prototype屬性,在父層宣告方法

使用prototype的屬性,讓move()宣告在父層,以便之後其子層可直接繼承。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.06.41.71.jpg

運行結果,可看到_proto_的物件內新增了move()的方法,這樣的寫法就不會產生重覆的move()了

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.06.56.71.jpg

可看到所產生的2個實例都可使用move()的方法。那是因為使用prototype在父層宣告方法後,子層繼承了父層的原因

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.07.11.12.jpg

運行結果,可看到2個slider和slider2的實例,都執行了move(),輸出字串moving

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.07.11.71.jpg

direction變數是宣告在slider物件內,而非prototype內。因此在各別實例化後,direction變數便會各自獨立(輸入forward和backward,這2個參數是各自獨立的)

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.08.20.12.jpg

運行結果,分別測出2個direction變數分別為forward和backward

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.08.21.71.jpg

強調在prototype宣告的方法(父層),仍可使用在子層宣告的變數direction

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.08.47.62.jpg

運行結果,成功合用位於父層的方法move(),和子層的變數direction來完成javascript內物件導向的基本應用

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.08.50.71.jpg

再次建議大家如要了解javascript物件導向的繼承概念,請看網站scriptjunkie的教學-

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.09.01.71.jpg

傳送html物件給類別-Slider,來設定屬性和方法

學會了基礎的繼承概念後,接下來我們開始一步步的將上一課程的Slider圖片捲動的功能,轉為更具結構的寫法。
首先,建立一個類別Slider,並將$('div.slider'),傳入此類別來供後續動作

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.09.59.17.jpg

先確定html的物件<div class="slider"></div>,有傳入Slider類別內了

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.10.01.75.jpg

function Slider(container,nav)//接收容納圖片的div.slider做為container參數,和放置按鈕的#slider-nav為nav參數,來加以設定Slider的屬性和方法。

Slider.prototype.transition//運算圖片的徧移位置

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.15.15.71.jpg

點選按鈕,移動圖片

slider.transition(-1800)//圖片移動間距設為-1800

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.16.52.71.jpg

運行結果,沒看到圖片?!因為移動了錯誤的div,包含圖片的div為$('div.slider ul')而非$('div.slider')

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.01.71.jpg

將Slider傳入的參數改為$('div.slider ul')

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.16.71.jpg

運行結果,正確位移-1800側image4的位置

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.21.17.jpg

依此類推,位移0為image1,-600為image2,-1200為image3

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.34.75.jpg

Slider.transition();//如果沒有輸入任何位移的數值,預計是會依序移動的

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.45.71.jpg

運行結果,點選Next按鈕,此功能尚未成功運作,因為尚未寫入current數值變動,來達到圖片移動的功能。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.17.48.67.jpg

current變數遞增遞減,控制圖片前後移動

透過判斷點選按鈕所傳入的dir參數是否為'next',來決定current要遞增或是遞減。
使用xx?xx:xx的判斷式為if else的簡寫法,你可自行選擇判斷式的寫法。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.20.23.71.jpg

在console中解說~~的功能//boolean值轉數字,true轉為1,false轉為0。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.21.19.71.jpg

(div === 'next')//為true,經~~轉為數值1
(div === 'prev')//為false,經~~轉為數值0

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.22.08.71.jpg

dir等於'next'時,this.current遞增1,否則遞增-1

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.24.15.58.jpg

運行結果,console檢測,點按next數值遞1, 點按prev遞減1

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.24.26.29.jpg

但減過頭會有負值產生喔,所以需修改判斷式

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.24.38.71.jpg

修正位移第一張和最後一張圖片的current判斷式

pos小於0時,就跳至圖片的最後一張

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.26.42.21.jpg

運行結果,在第一張img時,點選prev,console出this.current為3(已成功完成從第一張跳至最後一張的判斷式)

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.26.46.71.jpg

在console中解說%符號的功能

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.27.24.71.jpg

2%4 (2除以4,餘數為2)
1%4(1除以4,餘數為1)

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.27.36.17.jpg

4%4 (4除以4,餘數為0),根據此特性,第一張圖時,pos為0

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.27.48.25.jpg

pos(目前的圖片)%this.imgsLen(全部圖片數)
//第一張圖時,current為0,按next,(0+1)%4=1
//第二張圖時,current為1,按next,(1+1)%4=2
//第三張圖時,current為2,按next,(2+1)%4=3
//第四張圖時,current為3,按next,(3+1)%4=0(就會跳回第一張了)

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.27.51.71.jpg

作者使用skitch plus(手寫繪圖工具),來說曘%運算餘數的概念
6%4=2

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.28.37.71.jpg

完成結構化的Slider外掛

改名為setCurrent並回傳運算後的pos值

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.30.08.71.jpg

運用已完成的setCurrent的方法,來傳入移動方向的參數,來運到圖片前後移動的效果

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.30.53.71.jpg

運行結果,成功達成點按prev圖片跳至前一個,點按next圖片圖片跳至下一個的效果

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.30.59.71.jpg

但是圖片捲動的scrollbar還沒有隱藏

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.31.14.71.jpg

那是因為目前的css檔中,.slider{overflow:scroll;}//需設定為hiddeen才能將scrollbar隱藏

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.31.21.71.jpg

$('div.slider').css('overflow', 'hidden')//只有javascript有運作的瀏灠器才需將scrollbar設為hidden,關閉javascript的使用者,還是需要保留scrollbar,才留移動圖片。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.31.40.38.jpg

新增的container變數,取代原先的$('div.slider ul')傳給new Slider()。
Slider.nav.show()改成slider.nav,因要將控制是否要顯示的部份傳到獨立的slider.js來進行控制。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.32.16.71.jpg

this.nav = nav.show();//由傳入的nav參數來控制顯示

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.32.29.29.jpg

運行結果,scrollbar消失了,且功能正常運行

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.32.38.71.jpg

把javascript先刪掉,看看無js時,只有css的功能是否正常

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.32.44.71.jpg

運行結果,沒有js時,按鈕成功隱藏,只讓使用者透過scrollbar移動圖片的功能正常運行。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.32.47.33.jpg

結論,成功完成結構化的slider外掛。

/images/coding-note/javascript/jQuery-30day/15.Prototypal-Inheritance-and-Refactoring-the-Slider/15.Prototypal-Inheritance-and-Refactoring-the-Slider-0.33.26.71.jpg