2012-04-19 73 views
1

我有一個關於如何從面向對象的角度來處理特定問題的概念性問題(注意:對於那些對這裏的命名空間感興趣的人,我正在使用Google Closure)。我對OOP JS遊戲相當陌生,所以任何和所有的見解都很有幫助!面向對象的Javascript和多個DOM元素

想象一下,您想創建一個對象,該對象爲頁面上的每個DOM元素啓動輪播,該類型與類名.carouselClassName相匹配。

像這樣的事情

/* 
* Carousel constructor 
* 
* @param {className}: Class name to match DOM elements against to 
* attach event listeners and CSS animations for the carousel. 
*/ 
var carousel = function(className) { 
    this.className = className; 

    //get all DOM elements matching className 
    this.carouselElements = goog.dom.getElementsByClass(this.className); 
} 

carousel.prototype.animate = function() { 
    //animation methods here 
} 

carousel.prototype.startCarousel = function(val, index, array) { 
    //attach event listeners and delegate to other methods 
    //note, this doesn't work because this.animate is undefined (why?) 
    goog.events.listen(val, goog.events.EventType.CLICK, this.animate); 
} 

//initalize the carousel for each 
carousel.prototype.init = function() { 
    //foreach carousel element found on the page, run startCarousel 
    //note: this works fine, even calling this.startCarousel which is a method. Why? 
    goog.dom.array.foreach(this.className, this.startCarousel, carousel); 
} 

//create a new instance and initialize 
var newCarousel = new carousel('carouselClassName'); 
newCarousel.init(); 

只是OOP玩弄JS中的第一次,我做了一些意見:

  1. 在我的構造函數對象定義的屬性(this.classname)可通過其他原型對象中的this操作獲得。
  2. 在我的構造函數對象或原型中定義的方法無法使用this.methodName(請參閱上面的註釋)。

任何額外的我對待這一意見是絕對歡迎的。

+0

構造函數應該命名爲大寫。 – Bergi 2012-04-19 17:20:50

回答

2

我建議您沒有Carousel對象代表頁面上的所有輪播。每個應該是Carousel的新實例。

您遇到的問題與this未正確分配可以通過在您的構造函數中將這些方法「綁定」到this來解決。

E.g.

function Carousel(node) { 
    this.node = node; 

    // "bind" each method that will act as a callback or event handler 
    this.bind('animate'); 

    this.init(); 
} 
Carousel.prototype = { 
    // an example of a "bind" function... 
    bind: function(method) { 
     var fn = this[method], 
      self = this; 
     this[method] = function() { 
      return fn.apply(self, arguments); 
     }; 
     return this; 
    }, 

    init: function() {}, 

    animate: function() {} 
}; 

var nodes = goog.dom.getElementsByClass(this.className), 
    carousels = []; 

// Instantiate each carousel individually 
for(var i = 0; i < nodes.length; i++) carousels.push(new Carousel(nodes[i])); 
+0

謝謝。這是我實際要問的下一個問題 - 我同意每個輪播實例化個別更合適。感謝您的展示!一個後續問題是:將這些方法綁定到「this」。我發現這個(http://stackoverflow.com/questions/6527192/google-closure-bind-resolve-issues-with-the-this-keyword)。答案指出,你通常應該能夠繞過使用goog.bind(Closure爲你處理它)。那麼,我怎樣才能以不同的方式來構造這個結構以避免綁定事件? – djreed 2012-04-19 21:54:00

1

看一看的reference for the this keyword。如果您調用您的newCarousel對象中的某個方法(例如:newCarousel.init();),則init方法中的this將指向該對象。如果你打電話的方法,它是一樣的。

您總是可以從對象引用中檢索屬性。如果這些屬性是函數,並且不會在正確的上下文中執行(例如來自事件處理程序),則它們的this不會再指向newCarousel。使用bind()來解決(forEach似乎將您的第三個參數作爲每個調用的上下文)。

+1

我認爲forEach的第三個參數可能會照顧到......我不使用閉合,所以我不確定...... – Prestaul 2012-04-19 17:30:07

+0

啊,當然。 OP說它有效 - 儘管我不明白爲什麼,因爲我不知道lib。更新了答案。 – Bergi 2012-04-19 17:35:58