【问题标题】:Java Script Revealing Module Pattern create multiple objectsJavascript Revealing Module Pattern 创建多个对象
【发布时间】:2014-02-20 13:49:31
【问题描述】:

我需要关于以 Revealing Module Pattern 方式编写更好代码的建议。我遵循了教程http://weblogs.asp.net/dwahlin/archive/2011/09/05/creating-multiple-javascript-objects-when-using-the-revealing-module-pattern.aspx,这对我理解这种模式的基础知识有很大帮助。我正在尝试创建基本的图像滑块。请检查 jsfiddle 链接,

http://jsfiddle.net/sWtDf/

var Slider = window.Slider = window.Slider || {};

    Slider = (function($){

        var $reelWrap = $('.fnSlider'),
            $reel = $('.fnSlider').children('ul'),
            $slide = $reel.children('li'),
            slideWidth = $slide.width(),
            numSlides = $slide.length,                
            reelWidth = numSlides*slideWidth,
            $prev = $('.prev'),
            $next = $('.next'),

            init = function(){   
                pageLoad();               
                nextSlide();
                prevSlide();
            },

            pageLoad = function(){
                var index = 2;                                  
                $reel.css('width', reelWidth);
                $slide.eq(index).addClass('fnActive');     
                $reel.css('left', -(index*slideWidth));
            }

            nextSlide = function(){ 

                $next.click(function(e){
                    e.preventDefault();

                    var index = $reel.children('.fnActive').index() + 1;
                    var scroll = index * slideWidth;

                    if(index < numSlides){
                        $reel.animate({left: -(scroll)}).children().removeClass('fnActive');
                        $slide.eq(index).addClass('fnActive');
                    }else{
                       $reel.animate({left: 0}).children().removeClass('fnActive'); 
                       $slide.eq(0).addClass('fnActive');
                    }

                });

            },

            prevSlide = function(){ 

                $prev.click(function(e){
                    e.preventDefault();

                    var index = $reel.children('.fnActive').index() - 1;
                    var scroll = index * slideWidth;
                    var lastScroll = (numSlides-1) * slideWidth;

                    if(index == "-1"){
                         $reel.animate({left: -(lastScroll)}).children().removeClass('fnActive');
                         $slide.eq(-1).addClass('fnActive');
                    }else{
                        $reel.animate({left: -(scroll)}).children().removeClass('fnActive');
                        $slide.eq(index).addClass('fnActive');  
                    }

                });

            }

            return {
                init: init
            }


    })(jQuery);

    $(function(){

        Slider.init();

    });

我想知道的是——

1) 有没有更好的方法在代码审查后编写相同的轮播功能

2)我尝试过如何创建多个对象(实例) -

        var slider1, slider2;

        slider1 = Slider();
        slider2 = Slider();

        slider1.init();
        slider2.init();

导致错误 TypeError: Slider is not a function

3) 保持全局和私有函数的正确方法吗

4) 建议(如果有)

感谢您抽出宝贵的时间:)

【问题讨论】:

    标签: javascript jquery revealing-module-pattern


    【解决方案1】:

    如果你想创建多个实例,我建议你在你的模块中返回一个构造函数:

    var Slider = (function($){
    
        function slider(id){  // <- 'foo' is an example of a constructor argument 
                              // (1 and 12 below when the instances are created)
    
            this.id = id; // <- something specific for each instance
            // this.$reelWrap = ...
        }
    
        slider.prototype = {
    
            init: function(){
                this.pageLoad();
            },
    
            pageLoad: function(){
                 console.log('pageLoad called from instance with id', this.id);
            },
    
            getId: function(){
                return this.id; // <- 'this' refers to the current instance
            }
        };
    
        return slider;
    
    })(jQuery);
    
    var slider1 = new Slider(1);
    var slider2 = new Slider(12);
    
    console.log(slider1.getId());
    

    var Vehicle = function(engine, speed){
        this.engine = engine;
        this.speed = speed || "786km/Hr";    
    } 
    
    Vehicle.prototype.engineInfo = function(){
        console.log("this vehicle has engine " + this.engine);
    }
    
    var Porsche = function(engine, speed, carName){                                       
    
        Vehicle.apply(this, arguments);   
    
    // I stucked here and got answer 
    // http://stackoverflow.com/questions/8605788/
    // javascript-call-and-apply-functions-only-called-on-first-argument
    // it means Vehicle functions arguments got copied here am I right :)
    
    // J: The point is to call the 'base class' contructor with the arguments
    // that you provide when you create a new Porsche as well.
    // In other words, engine and speed will be set correctly in the 
    // Vehicle constructor when you create a new Porsche()
    
        this.carName = carName;
    }
    
    Porsche.prototype = Object.create(Vehicle.prototype);
    // Porsche.prototype = new Vehicle();
    // http://stackoverflow.com/questions/4166616/
    // understanding-the-difference-between-object-
    // create-and-new-somefunction-in-j
    // hmm need    more time to go into this :) 
    
    // J: The difference is that if you just do Porsche.prototype = new Vehicle();
    // The Vehicle constructor will be called even if you don't create an instance
    // of Porsche
    
    Porsche.prototype.constructor = Porsche;
    // I stucked here and got http://stackoverflow.com/questions/9343193/
    // why-set-prototypes-constructor-to-its-constructor-function
    
    // J: I would say that it's good practice to do it, but I've personally never
    // found any uses of that property.
    
    Porsche.prototype.speedInfo = function(){
        console.log("this vehicle has speed " + this.speed);
    }
    
    var cayMan1 = new Porsche("Engine UV", "500km/hr", "CayMan");
    var cayMan2 = new Porsche("Engine Ultra", "100km/hr", "911"); 
    
    cayMan2.engineInfo();        
    cayMan2.speedInfo();
    

    【讨论】:

    • @ Johan 感谢您的回复和详细的代码 sn-p :) 更进一步我做了这个 ex-1 jsfiddle.net/LXNgD/2 - 它是正确的还是可以用这个做更好的?我也试过像 ex-2 jsfiddle.net/nex2k 这样可以帮助我扩展和覆盖方法。使用 ex-1 我无法覆盖 slider1.nextSlide 方法任何建议
    • @PravinVaichal 好吧,简而言之,您似乎已经掌握了窍门。如果您想扩展和覆盖方法,我建议您创建一个“基础”滑块并让您的其他类型继承自它。如果你想要一个例子,请告诉我。
    • @Johan 首先感谢您为此付出的宝贵时间。一个例子会很棒:) 根据我的编码知识,可以通过显示模块模式、面向对象(使用原型创建实例及其灵活)、jQuery 插件来实现这一功能,如果你有时间可以解释一下 - 对于任何 js 功能如何确定哪种方法是有益的,如果具体有任何原因。 :)
    • @PravinVaichal 没问题。我刚从酒吧回家,所以请耐心等待。不确定这是否是最好的例子,但是嘿...jsfiddle.net/ERW4v 如果您有任何问题,请告诉我。我没有完全理解您所要求的所有内容,但不要将其与 jQuery 插件混淆。插件在一定程度上可能有用,但我更喜欢这样做。您始终可以将一组元素传递给构造函数,而不是执行$('.whatever').plugin()。换句话说,我会坚持你选择的模式
    • @ Johan - 谢谢,例如非常有帮助,并为迟到的回复道歉。我通过示例并尝试实现为 - jsfiddle.net/JGb8R/2 我也遇到了 - 揭示原型模式(你的第一个答案)我对其进行了更多探索 - jsfiddle.net/BV954 我想在多个实例的情况下最有帮助,扩展原型链,名称空间等。你有推特/电子邮件要关注吗? OOJS 现在对我来说更清楚了
    【解决方案2】:

    2) 你没有暴露 Slider

    
    var Slider = (function($){
    
      return function() {
        var $reelWrap = $('.fnSlider'),
        .........
      }
    }(jQuery))
    

    3) 一般来说,你的范围界定是好的..你不会暴露超过你必须的

    4) 你错过了第 4 题!!

    5) 如果有机会,您通常应该低买高卖

    【讨论】:

    • @ilan berci 感谢您的宝贵时间和 cmets 问题编号已更正,请您详细说明 5) 我没有完全理解
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多