【问题标题】:Object Oriented Javascript and Multiple DOM Elements面向对象的 Javascript 和多个 DOM 元素
【发布时间】:2012-05-01 06:37:33
【问题描述】:

我有一个关于如何从面向对象的角度处理特定问题的概念性问题(注意:对于那些对此处的命名空间感兴趣的人,我使用的是 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(参见上面的 cmets)。

绝对欢迎任何关于我的方法的额外 cmets :)

【问题讨论】:

  • 构造函数应该大写。

标签: javascript oop closures


【解决方案1】:

我建议您不要让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”。我发现了这个(stackoverflow.com/questions/6527192/…)。答案表明您通常应该能够使用 goog.bind 绕过(Closure 会为您处理)。那么,我该如何以不同的方式构建它以避免绑定事件?
【解决方案2】:

看看reference for the this keyword。如果从newCarousel 对象中调用其中一种方法(例如:newCarousel.init();),init 方法中的this 将指向该对象。如果你调用一个方法,它是一样的。

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

【讨论】:

  • 我认为 forEach 的第三个参数可能会解决这个问题......虽然我不使用 Closure,所以我不确定......
  • 啊,当然。 OP 说它有效——虽然我不明白为什么,因为我不知道这个库。更新了答案。
猜你喜欢
  • 1970-01-01
  • 2011-10-21
  • 2011-11-06
  • 2011-06-12
  • 2012-12-12
  • 2011-04-18
  • 1970-01-01
  • 2019-02-24
  • 1970-01-01
相关资源
最近更新 更多