2016-03-07 118 views
1

我正试图围绕不同模块模式的偏移量进行打包。我看到写这些模块和暴露他们的数据的不同方式。JavaScript模块模式差异

我在期待有关优缺点的信息,这里没有描述的更好的模式以及它们中的每一个的用例。


A)对象文字包装在自调用函数,发射了用init方法:(source)

(function() { 

var MyModule = { 
    settings: { 
    someProperty: 'value'; 
    } 

    init: function() { 
    someMethod(); 
    } 

    someMethod: function() { 
    // ... 
    } 
}; 

MyModule.init(); 
})(); 

This是的一个例子的简单的 “鸣叫这种” 实用程序我建立。我是否正确使用此模式?到目前为止,这是我唯一一个有实际写作经验的人。


B)模块的名称空间的自调用匿名函数:(source)

var MyModule = (function() { 
    var MyObj = {} 

    function privateMethod() { 
    // ... 
    } 

    MyObj.someProperty = 1; 
    MyObj.moduleMethod = function() { 
    // ... 
    }; 

    return MyObj; 
}()); 

是否有比以往的风格有什么优势/劣势?另外,在这里使用对象文字符号的含义是什么,而不是示例中的点语法?对象文字看起来更简洁,但我并没有真正意识到每个用例的恰当用例。


C)模块作为命名空间自调用匿名功能,而只能通过一个return块暴露期望的结果:(source)

var MyModule = (function() { 
    var myPrivateVar, myPrivateMethod; 

    myPrivateVar = 0; 

    myPrivateMethod = function(foo) { 
    console.log(foo); 
    }; 

    return { 
    myPublicVar: "foo", 

    myPublicFunction: function(bar) { 
     myPrivateVar++; 
     myPrivateMethod(bar); 
    } 
    }; 

})(); 

类似于先前的样式,而是暴露的的整个对象及其所有属性/方法,我们只是通过return声明暴露特定的数据位。


d)模块作为包裹在自调用匿名功能的功能,具有嵌套函数作为方法。该模块通过窗口对象暴露,然后经由new关键字构造:(source)

(function(window, undefined) { 

    function MyModule() { 

    this.myMethod = function myMethod() { 
     // ... 
    }; 

    this.myOtherMethod = function myOtherMethod() { 
     // ... 
    }; 

    } 

    window.MyModule = MyModule; 

})(window); 

var myModule = new MyModule(); 
myModule.myMethod(); 
myModule.myOtherMethod(); 

我假设这图案的强度是如果模块是一个种类,其中多个实体可能需要的“模板”存在于应用程序中。任何一个好的用例的具体例子?

+1

你应该看看Addy Osmani的书Javascript Design Patterns。它为初学者介绍了这个主题。你可以在这里免费阅读https://addyosmani.com/resources/essentialjsdesignpatterns/book/ – nick

+1

这是一个非常广泛的问题... –

回答

2

所有这些使用相同的模式只是略有不同的方式。

A)对象文字包装在一个自调用函数,与init方法发射了:

这是好的,如果你不打算让任何人访问的代码块。你甚至不需要有一个init函数。将代码封装在IIFE(立即调用的函数表达式)中可防止全局命名空间污染,并允许使用“私有”变量。在我看来,这只是一个好习惯,而不是一个模块。

B)模块的名称空间的自调用匿名函数:

这是当他们谈论模块模式是什么人的意思。它给你私有变量和函数,然后通过公共接口公开这些变量和函数。在你的例子中,该接口恰好被称为MyObj

C)模块作为命名空间自调用匿名功能,而只能通过一个return块暴露期望的结果:

这实际上是完全一样的东西一个。唯一的区别是,接口上的方法不能像在B中那样直接引用接口本身。例如:

MyObj.methodA = function() { 
    return MyObj.methodB(); 
}; 

,因为你必须引用它一个名称,但只有当你希望公众的方法来使用除返回的对象执行上下文的任何其他被称为有用将与之前的例子。即,setTimeout(MyModule.methodA)(将与全局上下文被调用,从而旨在this.methodB()是行不通的。

d)模块作为包裹在自调用匿名功能的功能,具有嵌套函数作为方法。该模块通过窗口对象暴露,然后通过new关键字构造:

与前2个相同的东西除了2个小差异。 window作为参数传递是因为历史上,访问局部变量比全局变量更快,因为引擎不必爬上作用域链。然而,现在大多数JS引擎优化访问window,因为它是常见的并且是已知的对象。同样,undefined作为参数给出,没有任何参数作为参数传递。这可确保您拥有正确的undefined值。这背后的原因是,从技术上讲,您可以在非严格模式下为undefined指定任何值。这意味着某些第三方可能会写入undefined = true;,并且突然所有undefined检查都失败。

另一个区别是,你正在返回一个函数,而不是一个对象。这背后的好处是,您可以拥有在每个对象实例中共享的私有变量以及每个实例的私有变量。示例:

var count = 0; 
function MyObject(id) { 
    var myID = id; 
    count++; 

    // Private ID 
    this.getID = function() { 
    return myID; 
    }; 

    // Number of instances that have been created 
    this.getCount = function() { 
    return count; 
    }; 
} 

这样做的缺点是您没有将方法附加到原型。这意味着JS引擎必须为每个对象的单个实例创建一个全新的函数。如果它在原型上,所有实例将共享相同的函数,但不能有单独的私有变量。

+1

强烈的解释已经清除了很多细节我失踪了 - 谢谢! –