面向对象的Javascript和多个DOM元素

Object Oriented Javascript and Multiple DOM Elements

本文关键字:DOM 元素 Javascript 面向对象的      更新时间:2023-09-26

我有一个概念性问题,关于如何从面向对象的角度处理特定问题(注意:对于那些对这里的命名空间感兴趣的人,我使用的是Google Closure)。我对OOP JS游戏相当陌生,所以任何见解都是有帮助的!

假设您要创建一个对象,该对象为页面上与类名.carouselClassName匹配的每个 DOM 元素启动轮播。

像这样的东西

/*
 * 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();

只是第一次在JS中玩OOP,我做了一些观察:

  1. 在我的构造函数对象(this.classname)中定义的属性可以通过其他原型对象中的this操作使用。
  2. 在我的构造函数对象或原型中定义的方法无法使用this.methodName(请参阅上面的注释)。

对我的方法提出任何其他评论绝对欢迎:)

我建议您不要让Carousel对象代表页面上的所有轮播。每个都应该是Carousel的新实例。

您遇到的未正确分配this的问题可以通过将这些方法"绑定"到构造函数中的this来解决。

例如

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]));

查看 this 关键字的引用。如果从newCarousel对象调用其中一个方法(例如:newCarousel.init(); ),则 init 方法中的this将指向该对象。如果你对此调用一个方法,它是相同的。

始终可以从对象引用中检索属性。如果这些属性是函数,并且不会在正确的上下文中执行(例如,从事件处理程序),则它们的this将不再指向newCarousel。使用bind()来解决这个问题(forEach似乎将你的第三个参数作为每次调用的上下文)。