类仿真 - 模块模式与功能对象

时间:2012-05-13 20:46:31

标签: javascript

  

可能重复:
  Javascript: Module Pattern vs Constructor/Prototype pattern?

我想在javaScript中使用类模拟。这是一种偏好。

我一直在使用模块模式,但我正在考虑只使用一个简单的函数对象,因为我可以创建公共和私有成员变量和函数。

Here是模拟类的函数对象的示例:

var input = document.getElementById('input');
var output = document.getElementById('output');

function test()
{
    var private_var = 'private_var';
    var private_func = function(){ return 'private_func';};
    var my = {};
    my.public_var = 'public_var';
    my.public_func = function(){ return 'public_func';};
    return my;
}

var object_test = new test();

alert( '| ' + object_test.public_var);
alert( '| ' + object_test.private_var);

alert( '| ' + object_test.public_func() );
alert( '| ' + object_test.private_func() );

​

Here是模拟类的模块模式的一个示例。

主要区别是什么?除了隐含全局显式的能力之外,还有吗?

2 个答案:

答案 0 :(得分:1)

我可能误解了“功能对象”的含义,但据我所知,这些模式并不是真正可以互换的。

“模块模式”用于根据需要定义具有方法和属性的单个对象。一个很好的例子是Math,自定义模块的一个简单示例只是一个Object实例:

var Module = { prop: 'prop' };
alert(Module.prop);

但是,通过这种方式,模块不是类。您无需致电new Math即可使用它们。您只需调用他们的方法(Math.abs())或获取/设置其属性(Math.PI)。

函数对象” - 或者我所说的构造函数 - 是最接近JavaScript的“类”定义的概念。 ObjectStringArray。这些和其他是为创建新实例而定义的构造函数。

您提供的代码段当然可以修改为构造函数:

// common-practice: constructors are named in PascalCase
function Test()
{
    var private_var = 'private_var';
    var private_func = function(){ return 'private_func';};

    this.public_var = 'public_var';
    this.public_func = function(){ return 'public_func';};
}

var object_test = new Test();

此外,这些模式不一定是相互排斥的。像模块一样处理构造函数将允许定义“静态”类成员:

var Foo = (function () {
    function constructor() {
        var private_var = 'private_var';
        this.public_prop = 'public_prop';
    }

    var private_shared = 'private_shared';
    constructor.public_shared = 'public_shared';

    return constructor;
})();

alert(Foo.public_shared);     // 'public_shared' (module property)
alert(new Foo().public_prop); // 'public_prop'   (instance property)

答案 1 :(得分:0)

我认为主要问题是你的test()函数仍然可以在没有new关键字的情况下调用,在这种情况下'this'的值将指向被调用者上下文(很可能是全局),而不是test()内部闭包,导致不良影响,例如污染全局命名空间和不同实例覆盖彼此的值。如果将构造函数作为常规函数调用,解释器将不会警告您。如果您的代码不是为了与优秀的受众共享,并且您正在使用构造函数的一些命名约定,例如构造函数的Test()和常规函数的test(),那么您仍然是安全的。 它还有助于在代码中保留一些规则,例如强制您在return语句中定义任何“公共”成员,其中所有成员都将相邻,充当干净的外观。这在大型代码库中很有意思。