ExtJS(JavaScript)模块设计模式最佳实践

blo*_*ong 12 javascript oop design-patterns extjs extjs3

我对模块设计模式的最佳实践有疑问.下面的代码是我们编写一些组件的方式的一个例子(我们使用ExtJs,但这不应该太重要).我们构建了很多这样的组件,我知道这与最佳实践完全不符.有任何想法清理代码?

Ext.ns("TEAM.COMPONENT");

function Foo() {

    // Private vars
    var privateNumber=0, myButton, privateInternalObject;

    var numberField = new Ext.form.NumberField({
        label : 'A NumberField!',
        listeners : {
            'change' : function(theTextField, newVal, oldVal) {
                console.log("You changed: " + oldVal + " to: " + newVal);
            }
        }
    });

    // Some private methods
    function changeNumField(someNumber) {
        numberField.setValue(someNumber);
    }

    // Some public methods
    this.publicFunctionSetNumToSomething() {
        changeNumField(privateNumber); 
    }

    /**
     * Initializes Foo
     */
    function init() {
        // Do some init stuff with variables & components
        myButton  = new Ext.Button({
            handler : function(button, eventObject) {
                console.log("Setting " + numberField + " to zero!");
                changeNumField(0);
            },
            text : 'Set NumberField to 0'

        });

        privateInternalObject = new SomeObject();
        word = "hello world";
        privateNumber = 5; 
    }

    init();

    return this;

};
Run Code Online (Sandbox Code Playgroud)

我想知道关于这一点的一些事情,并想要询问并进行对话:

  1. 在声明变量时(即在Foo的顶部)初始化变量有多重要
  2. 如果此模块的客户端达到其foo对象需要重新设置为其原始状态的状态,我该如何重新初始化此对象的一部分
  3. 这种设计会导致什么样的内存问题,以及如何重构以降低风险?
  4. 我在哪里可以了解更多?是否有任何文章可以解决这个问题,而不必过多依赖最新和最伟大的EcmaScript 5?

更新2012-05-24 我只想添加,我认为这个问题( Extjs:通过构造函数或initComponent扩展类?)与对话非常相关,特别是考虑到最高投票答案来自"前Ext JS co-创始人和核心开发者"

更新2012-05-31 另外一个补充,这个问题也应该链接(使用ExtJS扩展类时的私有成员).此外,这是我最喜欢的实现:

/*jshint smarttabs: true */
/*global MY, Ext, jQuery */
Ext.ns("MY.NAMESPACE");

MY.NAMESPACE.Widget = (function($) {
    /**
     * NetBeans (and other IDE's) may complain that the following line has
     * no effect, this form is a useless string literal statement, so it 
     * will be ignored by browsers with implementations lower than EcmaScript 5.
     * Newer browsers, will help developers to debug bad code.
     */
    "use strict";

    // Reference to the super "class" (defined later)
    var $superclass = null;

    // Reference to this "class", i.e. "MY.NAMESPACE.Widget"
    var $this = null;

    // Internal reference to THIS object, which might be useful to private methods
    var $instance = null;

    // Private member variables
    var someCounter, someOtherObject = {
        foo: "bar",
        foo2: 11
    };

    ///////////////////////
    /* Private Functions */
    ///////////////////////
    function somePrivateFunction(newNumber) {
        someCounter = newNumber;
    }

    function getDefaultConfig() {
        var defaultConfiguration = {
            collapsible: true,
            id: 'my-namespace-widget-id',
            title: "My widget's title"
        };
        return defaultConfiguration;
    }

    //////////////////////
    /* Public Functions */
    //////////////////////
    $this = Ext.extend(Ext.Panel, {
        /**
         * This is overriding a super class' function
         */
        constructor: function(config) {
            $instance = this;
            config = $.extend(getDefaultConfig(), config || {});

            // Call the super clas' constructor 
            $superclass.constructor.call(this, config);
        },
        somePublicFunctionExposingPrivateState: function(clientsNewNumber) {
            clientsNewNumber = clientsNewNumber + 11;
            somePrivateFunction(clientsNewNumber);
        },
        /**
         * This is overriding a super class' function
         */
        collapse: function() {
            // Do something fancy
            // ...
            // Last but not least
            $superclass.collapse.call(this);
        }
    });

    $superclass = $this.superclass;
    return $this;

})(jQuery);?
Run Code Online (Sandbox Code Playgroud)

mVC*_*Chr 5

首先,这不是我所知道的模块设计模式,这是一个通用的构造模式.我知道的模块模式是单例,但在这里你可以有很多Foo()实例.话虽如此...

问:在声明变量时(即在Foo的顶部)初始化变量有多重要

为了清晰起见,将它们声明为顶部非常重要,但是初始化它们并不重要,因为您在init中这样做.如果您没有这样做,初始化它们可以防止您在稍后测试变量之前必须进行未定义的检查:

var x;

function baz(){
    if (typeof(x) === 'undefined') {
        // init
    } else {
        if (x > 0) { blah } else { blah blah }
    }
}
Run Code Online (Sandbox Code Playgroud)

问:如果此模块的客户端达到foo对象需要重新设置为原始状态的状态,我该如何重新初始化此对象的一部分

创建公共重置方法有什么问题吗?它可以访问私有变量.

function Foo() {
    // ...

    this.reset = function () {
        privateNumber = 0;
        // etc
    };

    // ...
}
Run Code Online (Sandbox Code Playgroud)

问:这种设计可能导致什么样的内存问题?如何重构以降低风险?

我不知道.

问:我在哪里可以了解更多信息?是否有任何文章可以解决这个问题,而不必过多依赖最新和最伟大的EcmaScript 5?

这里有一个关于Javascript模块(和其他)模式的很好的阅读:http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript