How do I create a namespace in JavaScript so that my objects and functions aren't overwritten by other same-named objects and functions? I've used the following:
如何在JavaScript中创建一个名称空间,这样我的对象和函数就不会被其他相同命名的对象和函数覆盖?我使用了以下几点:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Is there a more elegant or succinct way of doing this?
这样做是否有更优雅或简洁的方式?
26 个解决方案
#1
707
I like this:
我喜欢这个:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
#2
1012
I use the approach found on the Enterprise jQuery site:
我使用了企业jQuery站点上的方法:
Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function.
下面是他们的示例,展示如何声明私有和公共属性和函数。一切都是作为一个自执行的匿名函数完成的。
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
So if you want to access one of the public members you would just go skillet.fry()
or skillet.ingredients
.
因此,如果你想要进入其中的一个公众成员,你只需要煎锅或煎锅。
What's really cool is that you can now extend the namespace using the exact same syntax.
真正酷的是,现在可以使用完全相同的语法扩展名称空间。
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
The third undefined
argument
The third,
undefined
argument is the source of the variable of valueundefined
. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variableundefined
is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable namedundefined
which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the valueundefined
.第三个,未定义的参数是未定义值变量的源。我不确定它是否仍然适用于今天,但是在使用较旧的浏览器/ JavaScript标准(ecmascript 5, JavaScript < 1.8.5 ~ firefox 4)时,未定义的全局范围变量是可写的,因此任何人都可以重写它的值。第三个参数(当没有传递一个值时)创建一个名为undefined的变量,该变量的作用域是名称空间/函数。因为在创建名称空间时没有传递任何值,因此默认值为未定义的值。
#3
331
Another way to do it, which I consider it to be a little bit less restrictive than the object literal form, is this:
另一种方法是,我认为它比物体的文字形式的限制性更小,是这样的
var ns = new function() {
var internalFunction = function() {
};
this.publicFunction = function() {
};
};
The above is pretty much like the module pattern and whether you like it or not, it allows you to expose all your functions as public, while avoiding the rigid structure of an object literal.
上面的内容非常类似于模块模式,不管您是否喜欢,它允许您公开所有的功能,同时避免了对象文字的僵硬结构。
#4
151
Is there a more elegant or succinct way of doing this?
这样做是否有更优雅或简洁的方式?
Yes. For example:
是的。例如:
var your_namespace = your_namespace || {};
then you can have
然后你可以有
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
#5
86
I normally build it in a closure:
我通常是在封闭的环境中构建它:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
My style over the years has had a subtle change since writing this, and I now find myself writing the closure like this:
多年来,我的写作风格发生了微妙的变化,我现在发现自己写的是这样的结尾:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
In this way I find the public API and implementation easier to understand. Think of the return statement as being a public interface to the implementation.
通过这种方式,我发现公共API和实现更容易理解。将返回语句看作是实现的公共接口。
#6
55
Because you may write different files of JavaScript and later combine or not combine them in an application, each needs to be able to recover or construct the namespace object without damaging the work of other files...
因为您可以编写不同的JavaScript文件,然后在应用程序中合并或不合并它们,因此每个都需要能够在不损坏其他文件的工作的情况下恢复或构造名称空间对象。
One file might intend to use the namespace namespace.namespace1
:
一个文件可能打算使用名称空间名称空间。
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
Another file might want to use the namespace namespace.namespace2
:
另一个文件可能希望使用名称空间名称空间。
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
These two files can live together or apart without colliding.
这两个文件可以在不碰撞的情况下共存或分离。
#7
45
Here's how Stoyan Stefanov does it in his JavaScript Patterns book which I found to be very good (it also shows how he does comments that allows for auto-generated API documentation, and how to add a method to a custom object's prototype):
这是Stoyan Stefanov在他的JavaScript模式书籍中所做的,我发现它非常好(它还展示了他如何评论,允许自动生成的API文档,以及如何向自定义对象的原型添加方法):
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};
#8
32
I use this approach:
我用这个方法:
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
External code can then be:
外部代码可以是:
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);
#9
32
This is a follow-up to user106826's link to Namespace.js. It seems the project moved to GitHub. It is now smith/namespacedotjs.
这是user106826与Namespace.js链接的后续操作。似乎该项目转移到了GitHub。现在史密斯/ namespacedotjs。
I have been using this simple JavaScript helper for my tiny project and so far it seems to be light yet versatile enough to handle namespacing and loading modules/classes. It would be great if it would allow me to import a package into a namespace of my choice, not just the global namespace... sigh, but that's besides the point.
我一直在为我的小项目使用这个简单的JavaScript助手,到目前为止,它看起来还很轻,而且还可以处理命名空间和装载模块/类。如果它允许我将一个包导入到我所选择的名称空间中,而不仅仅是全局名称空间,那就太好了。叹气,但这不是重点。
It allows you to declare the namespace then define objects/modules in that namespace:
它允许您声明名称空间,然后在该名称空间中定义对象/模块:
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
Another option is to declare the namespace and its contents at once:
另一种方法是立即声明命名空间和它的内容:
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
For more usage examples, look at the example.js file in the source.
有关更多的用法示例,请参见示例。js文件在源代码中。
#10
29
Sample:
示例:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert('onTimeout')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call 'namespace.module1.init();' from outside the module. */
return self;
})()
You can optionally declare a local
variable, same
, like self
and assign local.onTimeout
if you want it to be private.
您可以选择声明一个本地变量,与self一样,并分配本地变量。onTimeout,如果你想让它是私有的。
#11
13
You can declare a simple function to provide namespaces.
您可以声明一个简单的函数来提供名称空间。
function namespace(namespace) {
var object = this, tokens = namespace.split("."), token;
while (tokens.length > 0) {
token = tokens.shift();
if (typeof object[token] === "undefined") {
object[token] = {};
}
object = object[token];
}
return object;
}
// Usage example
namespace("foo.bar").baz = "I'm a value!";
#12
9
I created namespace which is inspired by Erlang's modules. It is a very functional approach, but that is how I write my JavaScript code these days.
我创建了由Erlang模块所启发的名称空间。这是一种非常实用的方法,但这是我最近编写JavaScript代码的方式。
It gives a closure a global namespace and exposes a defined set functions within that closure.
它为一个全局命名空间提供了一个闭包,并在该闭包中公开一个已定义的集合函数。
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();
#13
8
I use the following syntax for the namespace.
我为名称空间使用以下语法。
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
jsfiddle:http://jsfiddle.net/rpaul/4dngxwb3/1/
#14
8
If you need the private scope:
如果你需要私人空间:
var yourNamespace = (function() {
//Private property
var publicScope = {};
//Private property
var privateProperty = "aaa";
//Public property
publicScope.publicProperty = "bbb";
//Public method
publicScope.publicMethod = function() {
this.privateMethod();
};
//Private method
function privateMethod() {
console.log(this.privateProperty);
}
//Return only the public parts
return publicScope;
}());
yourNamespace.publicMethod();
else if you won't ever use the private scope:
如果你不使用私人空间的话:
var yourNamespace = {};
yourNamespace.publicMethod = function() {
// Do something...
};
yourNamespace.publicMethod2 = function() {
// Do something...
};
yourNamespace.publicMethod();
#15
7
After porting several of my libraries to different projects, and having to constantly be changing the top level (statically named) namespace, I've switched to using this small (open source) helper function for defining namespaces.
在将几个库移植到不同的项目之后,并且必须不断地更改*(静态命名的)名称空间之后,我切换到使用这个小的(开源)helper函数来定义名称空间。
global_namespace.Define('startpad.base', function(ns) {
var Other = ns.Import('startpad.other');
....
});
Description of the benefits are at my blog post. You can grab the source code here.
对好处的描述在我的博客上。您可以在这里获取源代码。
One of the benefits I really like is isolation between modules with respect to load order. You can refer to an external module BEFORE it is loaded. And the object reference you get will be filled in when the code is available.
我真正喜欢的一个好处是,在加载顺序方面,模块之间是隔离的。在加载外部模块之前,您可以参考它。当代码可用时,将填充对象引用。
#16
7
The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering.
模块模式最初被定义为一种为传统软件工程的类提供私有和公共封装的方法。
When working with the Module pattern, we may find it useful to define a simple template that we use for getting started with it. Here's one that covers name-spacing, public and private variables.
在处理模块模式时,我们可能会发现定义一个简单的模板来开始使用它是很有用的。这是一个包括名字间距,公共和私有变量。
In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page.
在JavaScript中,模块模式用于进一步模拟类的概念,这样我们就可以将公共/私有方法和变量包括在单个对象中,从而屏蔽了全局范围内的特定部分。这导致我们的函数名称与页面上附加脚本中定义的其他函数相冲突的可能性降低了。
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
Advantages
优势
why is the Module pattern a good choice? For starters, it's a lot cleaner for developers coming from an object-oriented background than the idea of true encapsulation, at least from a JavaScript perspective.
为什么模块模式是一个好的选择?首先,对于来自面向对象背景的开发人员来说,它比真正封装的概念要干净得多,至少从JavaScript的角度来看是这样。
Secondly, it supports private data - so, in the Module pattern, public parts of our code are able to touch the private parts, however the outside world is unable to touch the class's private parts.
其次,它支持私有数据——因此,在模块模式中,代码的公共部分能够触及私有部分,但是外部世界无法触及类的私有部分。
Disadvantages
缺点
The disadvantages of the Module pattern are that as we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used.
模块模式的缺点是,当我们以不同的方式访问公共和私有成员时,当我们希望改变可见性时,我们实际上必须对每个成员使用的位置进行更改。
We also can't access private members in methods that are added to the object at a later point. That said, in many cases the Module pattern is still quite useful and when used correctly, certainly has the potential to improve the structure of our application.
我们也不能访问在稍后添加到对象的方法中的私有成员。这就是说,在许多情况下,模块模式仍然非常有用,并且在正确使用时,当然有可能改进我们的应用程序的结构。
The Revealing Module Pattern
显示模块的模式
Now that we're a little more familiar with the module pattern, let’s take a look at a slightly improved version - Christian Heilmann’s Revealing Module pattern.
现在我们对模块模式更熟悉了,让我们看一下稍微改进的版本——Christian Heilmann的揭示模块模式。
The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables.He also disliked the Module pattern’s requirement for having to switch to object literal notation for the things he wished to make public.
揭示模块的模式出现了,因为Heilmann对他不得不重复主对象的名称的事实感到沮丧,因为我们想从另一个公共方法调用一个公共方法或者访问公共变量。他也不喜欢模块模式的要求,即必须切换到对象文字符号,以实现他想要公开的东西。
The result of his efforts was an updated pattern where we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.
他的努力的结果是一个更新的模式,我们只需在私有范围内定义所有的函数和变量,然后返回一个匿名对象,并指向我们希望公开的私有功能。
An example of how to use the Revealing Module pattern can be found below
下面是一个如何使用揭示模块模式的示例。
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Advantages
优势
This pattern allows the syntax of our scripts to be more consistent. It also makes it more clear at the end of the module which of our functions and variables may be accessed publicly which eases readability.
此模式允许脚本的语法更加一致。它还使模块的末尾更加清晰,我们的函数和变量可以被公开访问,从而简化可读性。
Disadvantages
缺点
A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.
这种模式的缺点是,如果一个私有函数引用一个公共函数,那么如果需要一个补丁,那么公共函数就不能被覆盖。这是因为私有函数将继续引用私有实现,而模式并不适用于公共成员,只适用于函数。
Public object members which refer to private variables are also subject to the no-patch rule notes above.
引用私有变量的公共对象成员也要遵守上面的无补丁规则说明。
#17
6
I'm 7 years late to the party, but did quite a bit of work around this 8 years ago:
我已经迟到7年了,但8年前我做了很多工作:
- http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
- http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
- http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
- http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
It is important to be able to easily and efficiently create multiple nested namespaces to keep a complex web application organized and manageable, while respecting the JavaScript global namespace (preventing namespace pollution), and with not clobbering any existing objects in the namespace path while doing so.
很重要的一点是,能够轻松和高效地创建多个嵌套的名称空间,以保持复杂的web应用程序的组织和管理,同时尊重JavaScript全局名称空间(防止名称空间污染),并且在这样做的同时不阻塞名称空间路径中的任何现有对象。
From the above, this was my circa-2008 solution:
以上是我的circa-2008解决方案:
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
This isn't creating a namespace, but provides a function for creating namespaces.
这不是创建名称空间,而是为创建名称空间提供了一个函数。
This can be condensed to a minified one-liner:
这可以浓缩成一个小型的一行:
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
Example of use:
使用的例子:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
Or, as one statement:
或者,正如一个声明:
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
Either is then executed as:
要么被执行为:
com.example.namespace.test();
If you don't need support for legacy browsers, an updated version:
如果您不需要对遗留浏览器的支持,则需要更新版本:
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
Now, I'd be leery of exposing namespace
to the global namespace itself. (Too bad the base language doesn't provide this for us!) So I'd typically use this myself in a closure, such as:
现在,我希望将名称空间暴露给全局名称空间本身。(糟糕的是,基本语言并不能为我们提供这些!)所以我通常会在闭包中使用它,比如:
(function(){
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
const ns = namespace("com.ziesemer.myApp");
// Optional:
ns.namespace = ns;
// Further extend, work with ns from here...
}());
console.log("\"com\":", com);
In a larger application, this only needs to be defined once at the beginning of a page load (for client-based web apps). Additional files can then reuse the namespace function if kept (included as "optional" in the above). At worst, if this function is re-declared a few times - it's only a few lines of code, and less if minified.
在更大的应用程序中,这只需要在页面加载开始时定义一次(对于基于客户机的web应用程序)。如果保留了名称空间函数(包括在上面的“可选”),则可以重用其他文件。在最坏的情况下,如果这个函数被重新声明了几次——它仅仅是几行代码,如果缩小了就更少了。
#19
3
My favorite pattern has become lately this:
我最喜欢的模式是:
var namespace = (function() {
// expose to public
return {
a: internalA,
c: internalC
}
// all private
/**
* Full JSDoc
*/
function internalA() {
// ...
}
/**
* Full JSDoc
*/
function internalB() {
// ...
}
/**
* Full JSDoc
*/
function internalC() {
// ...
}
/**
* Full JSDoc
*/
function internalD() {
// ...
}
})();
Of course, return can be at the end, but if only function declarations follow it, it's much easier to see what's the namespace all about, and what API is exposed.
当然,返回可以在最后,但是如果只有函数声明遵循它,那么就更容易看到名称空间的全部内容,以及所暴露的API。
The pattern of using function expressions in such cases results in not being able to know what methods are exposed without going over the entire code.
在这种情况下,使用函数表达式的模式导致无法知道哪些方法在不经过整个代码的情况下被公开。
#20
1
Quite a follow-up of Ionuț G. Stan's answer, but showing the benefits of uncluttered code by using var ClassFirst = this.ClassFirst = function() {...}
, which takes advantage of JavaScript's closure scoping for less namespace cluttering for classes in the same namespace.
后续Ionuțg·斯坦的回答,但显示的好处使用var ClassFirst =这整洁的代码。ClassFirst = function(){…},它利用了JavaScript的闭包,为相同名称空间中的类提供了更少的命名空间。
var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
Output:
输出:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
#21
1
I like Jaco Pretorius' solution, but I wanted to make the "this" keyword a bit more useful by pointing it to the module/namespace object. My version of skillet:
我喜欢Jaco Pretorius的解决方案,但我希望通过将这个关键字指向模块/名称空间对象,使这个关键字更有用。我的版本的锅:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);
#22
1
We can use it independently in this way:
我们可以这样独立地使用它:
var A = A|| {};
A.B = {};
A.B = {
itemOne: null,
itemTwo: null,
};
A.B.itemOne = function () {
//..
}
A.B.itemTwo = function () {
//..
}
#23
0
If using a Makefile you can do this.
如果使用Makefile,您可以这样做。
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;
// clientfile.js
billy.bob();
I prefer to use a Makefile anyway once I get to about 1000 lines because I can effectively comment out large swaths of code by removing a single line in the makefile. It makes it easy to fiddle with stuff. Also, with this technique the namespace only appears once in the prelude so it's easy to change and you don't have to keep repeating it inside the library code.
我更倾向于使用Makefile,因为我可以使用大约1000行代码,因为我可以通过删除Makefile中的一行代码来有效地注释掉大量代码。这让你很容易摆弄东西。而且,使用这种技术,名称空间只会在序曲中出现一次,因此很容易更改,而且您不必在库代码中不断重复它。
A shell script for live development in the browser when using a makefile:
使用makefile时浏览器中实时开发的shell脚本:
while (true); do make; sleep 1; done
Add this as a make task 'go' and you can 'make go' to keep your build updated as you code.
将此添加为make任务'go',您可以'make go'以保持您的构建更新为您的代码。
#24
0
I've written another namespacing library that works a bit more like packages / units do in other languages. It allows you to create a package of JavaScript code and the reference that package from other code:
我编写了另一个命名空间库,它更像其他语言中的包/单元。它允许您创建一个JavaScript代码包,并从其他代码中引用该包:
File hello.js
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
File Example.js
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
Only the second file needs to be included in the page. Its dependencies (file hello.js in this example) will automatically be loaded and the objects exported from those dependencies will be used to populate the arguments of the callback function.
只有第二个文件需要包含在页面中。其依赖项(文件你好。在这个示例中,将自动加载并从这些依赖项中导出的对象将用于填充回调函数的参数。
You can find the related project in Packages JS.
您可以在包JS中找到相关的项目。
#25
0
My habit is to use function myName() as property storage, and then var myName as "method" holder...
我的习惯是使用函数myName()作为属性存储,然后使用var myName作为“方法”holder…
Whether this is legitimate enough or not, beat me! I am relying on my PHP logic all the time, and things simply work. :D
不管这是否合理,打我吧!我一直依赖于我的PHP逻辑,而事情只是简单地工作。:D
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log('Object creation failed!')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
if (this !==) myobject . fname1 ();其他myObj.fName2();
You can also do it in a 'vice versa' way to check before object creation which is much better:
你也可以用“反之亦然”的方式来检查对象的创建,这是更好的方法:
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log('myObj failed!');
debugger;
}
else
myObj.init();
Reference to this: JavaScript: Creating Object with Object.create()
引用这个:JavaScript:用Object.create()创建对象。
#26
0
In JavaScript there are no predefined methods to use namespaces. In JavaScript we have to create our own methods to define NameSpaces. Here is a procedure we follow in Oodles technologies.
在JavaScript中没有预定义的方法来使用名称空间。在JavaScript中,我们必须创建自己的方法来定义名称空间。这是我们在Oodles技术中遵循的一个过程。
Register a NameSpace Following is the function to register a name space
注册一个名称空间是注册一个名称空间的函数。
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
To register a Namespace just call the above function with the argument as name space separated by '.'
(dot). For Example Let your application name is oodles. You can make a namespace by following method
要注册一个名称空间,只需将上面的函数命名为“分隔的名称空间”。”(点)。例如,让您的应用程序名称为oodles。您可以通过以下方法创建名称空间。
registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
Basically it will create your NameSpaces structure like below in backend:
基本上,它将在后端创建您的名称空间结构:
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
In the above function you have register a namespace called "oodles.HomeUtilities"
and "oodles.GlobalUtilities"
. To call these namespaces we make an variable i.e. var $OHU
and var $OGU
.
在上面的函数中,您已经注册了一个名为“oodles”的名称空间。HomeUtilities”和“oodles.GlobalUtilities”。要调用这些名称空间,我们创建一个变量,即var $OHU和var $OGU。
These variables are nothing but an alias to Intializing the namespace. Now, Whenever you declare a function that belong to HomeUtilities
you will declare it like following:
这些变量只不过是命名空间的别名。现在,当你声明一个属于homeuti的函数时,你会声明如下:
$OHU.initialization = function(){
//Your Code Here
};
Above is the function name initialization and it is put into an namespace $OHU
. and to call this function anywhere in the script files. Just use following code.
上面是函数名初始化,它被放入一个名称空间$OHU中。在脚本文件的任何地方调用这个函数。用代码。
$OHU.initialization();
Similarly, with the another NameSpaces.
类似地,使用另一个名称空间。
Hope it helps.
希望它可以帮助。
#1
707
I like this:
我喜欢这个:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
#2
1012
I use the approach found on the Enterprise jQuery site:
我使用了企业jQuery站点上的方法:
Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function.
下面是他们的示例,展示如何声明私有和公共属性和函数。一切都是作为一个自执行的匿名函数完成的。
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
So if you want to access one of the public members you would just go skillet.fry()
or skillet.ingredients
.
因此,如果你想要进入其中的一个公众成员,你只需要煎锅或煎锅。
What's really cool is that you can now extend the namespace using the exact same syntax.
真正酷的是,现在可以使用完全相同的语法扩展名称空间。
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
The third undefined
argument
The third,
undefined
argument is the source of the variable of valueundefined
. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variableundefined
is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable namedundefined
which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the valueundefined
.第三个,未定义的参数是未定义值变量的源。我不确定它是否仍然适用于今天,但是在使用较旧的浏览器/ JavaScript标准(ecmascript 5, JavaScript < 1.8.5 ~ firefox 4)时,未定义的全局范围变量是可写的,因此任何人都可以重写它的值。第三个参数(当没有传递一个值时)创建一个名为undefined的变量,该变量的作用域是名称空间/函数。因为在创建名称空间时没有传递任何值,因此默认值为未定义的值。
#3
331
Another way to do it, which I consider it to be a little bit less restrictive than the object literal form, is this:
另一种方法是,我认为它比物体的文字形式的限制性更小,是这样的
var ns = new function() {
var internalFunction = function() {
};
this.publicFunction = function() {
};
};
The above is pretty much like the module pattern and whether you like it or not, it allows you to expose all your functions as public, while avoiding the rigid structure of an object literal.
上面的内容非常类似于模块模式,不管您是否喜欢,它允许您公开所有的功能,同时避免了对象文字的僵硬结构。
#4
151
Is there a more elegant or succinct way of doing this?
这样做是否有更优雅或简洁的方式?
Yes. For example:
是的。例如:
var your_namespace = your_namespace || {};
then you can have
然后你可以有
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
#5
86
I normally build it in a closure:
我通常是在封闭的环境中构建它:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
My style over the years has had a subtle change since writing this, and I now find myself writing the closure like this:
多年来,我的写作风格发生了微妙的变化,我现在发现自己写的是这样的结尾:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
In this way I find the public API and implementation easier to understand. Think of the return statement as being a public interface to the implementation.
通过这种方式,我发现公共API和实现更容易理解。将返回语句看作是实现的公共接口。
#6
55
Because you may write different files of JavaScript and later combine or not combine them in an application, each needs to be able to recover or construct the namespace object without damaging the work of other files...
因为您可以编写不同的JavaScript文件,然后在应用程序中合并或不合并它们,因此每个都需要能够在不损坏其他文件的工作的情况下恢复或构造名称空间对象。
One file might intend to use the namespace namespace.namespace1
:
一个文件可能打算使用名称空间名称空间。
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
Another file might want to use the namespace namespace.namespace2
:
另一个文件可能希望使用名称空间名称空间。
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
These two files can live together or apart without colliding.
这两个文件可以在不碰撞的情况下共存或分离。
#7
45
Here's how Stoyan Stefanov does it in his JavaScript Patterns book which I found to be very good (it also shows how he does comments that allows for auto-generated API documentation, and how to add a method to a custom object's prototype):
这是Stoyan Stefanov在他的JavaScript模式书籍中所做的,我发现它非常好(它还展示了他如何评论,允许自动生成的API文档,以及如何向自定义对象的原型添加方法):
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};
#8
32
I use this approach:
我用这个方法:
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
External code can then be:
外部代码可以是:
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);
#9
32
This is a follow-up to user106826's link to Namespace.js. It seems the project moved to GitHub. It is now smith/namespacedotjs.
这是user106826与Namespace.js链接的后续操作。似乎该项目转移到了GitHub。现在史密斯/ namespacedotjs。
I have been using this simple JavaScript helper for my tiny project and so far it seems to be light yet versatile enough to handle namespacing and loading modules/classes. It would be great if it would allow me to import a package into a namespace of my choice, not just the global namespace... sigh, but that's besides the point.
我一直在为我的小项目使用这个简单的JavaScript助手,到目前为止,它看起来还很轻,而且还可以处理命名空间和装载模块/类。如果它允许我将一个包导入到我所选择的名称空间中,而不仅仅是全局名称空间,那就太好了。叹气,但这不是重点。
It allows you to declare the namespace then define objects/modules in that namespace:
它允许您声明名称空间,然后在该名称空间中定义对象/模块:
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
Another option is to declare the namespace and its contents at once:
另一种方法是立即声明命名空间和它的内容:
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
For more usage examples, look at the example.js file in the source.
有关更多的用法示例,请参见示例。js文件在源代码中。
#10
29
Sample:
示例:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert('onTimeout')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call 'namespace.module1.init();' from outside the module. */
return self;
})()
You can optionally declare a local
variable, same
, like self
and assign local.onTimeout
if you want it to be private.
您可以选择声明一个本地变量,与self一样,并分配本地变量。onTimeout,如果你想让它是私有的。
#11
13
You can declare a simple function to provide namespaces.
您可以声明一个简单的函数来提供名称空间。
function namespace(namespace) {
var object = this, tokens = namespace.split("."), token;
while (tokens.length > 0) {
token = tokens.shift();
if (typeof object[token] === "undefined") {
object[token] = {};
}
object = object[token];
}
return object;
}
// Usage example
namespace("foo.bar").baz = "I'm a value!";
#12
9
I created namespace which is inspired by Erlang's modules. It is a very functional approach, but that is how I write my JavaScript code these days.
我创建了由Erlang模块所启发的名称空间。这是一种非常实用的方法,但这是我最近编写JavaScript代码的方式。
It gives a closure a global namespace and exposes a defined set functions within that closure.
它为一个全局命名空间提供了一个闭包,并在该闭包中公开一个已定义的集合函数。
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();
#13
8
I use the following syntax for the namespace.
我为名称空间使用以下语法。
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
jsfiddle:http://jsfiddle.net/rpaul/4dngxwb3/1/
#14
8
If you need the private scope:
如果你需要私人空间:
var yourNamespace = (function() {
//Private property
var publicScope = {};
//Private property
var privateProperty = "aaa";
//Public property
publicScope.publicProperty = "bbb";
//Public method
publicScope.publicMethod = function() {
this.privateMethod();
};
//Private method
function privateMethod() {
console.log(this.privateProperty);
}
//Return only the public parts
return publicScope;
}());
yourNamespace.publicMethod();
else if you won't ever use the private scope:
如果你不使用私人空间的话:
var yourNamespace = {};
yourNamespace.publicMethod = function() {
// Do something...
};
yourNamespace.publicMethod2 = function() {
// Do something...
};
yourNamespace.publicMethod();
#15
7
After porting several of my libraries to different projects, and having to constantly be changing the top level (statically named) namespace, I've switched to using this small (open source) helper function for defining namespaces.
在将几个库移植到不同的项目之后,并且必须不断地更改*(静态命名的)名称空间之后,我切换到使用这个小的(开源)helper函数来定义名称空间。
global_namespace.Define('startpad.base', function(ns) {
var Other = ns.Import('startpad.other');
....
});
Description of the benefits are at my blog post. You can grab the source code here.
对好处的描述在我的博客上。您可以在这里获取源代码。
One of the benefits I really like is isolation between modules with respect to load order. You can refer to an external module BEFORE it is loaded. And the object reference you get will be filled in when the code is available.
我真正喜欢的一个好处是,在加载顺序方面,模块之间是隔离的。在加载外部模块之前,您可以参考它。当代码可用时,将填充对象引用。
#16
7
The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering.
模块模式最初被定义为一种为传统软件工程的类提供私有和公共封装的方法。
When working with the Module pattern, we may find it useful to define a simple template that we use for getting started with it. Here's one that covers name-spacing, public and private variables.
在处理模块模式时,我们可能会发现定义一个简单的模板来开始使用它是很有用的。这是一个包括名字间距,公共和私有变量。
In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page.
在JavaScript中,模块模式用于进一步模拟类的概念,这样我们就可以将公共/私有方法和变量包括在单个对象中,从而屏蔽了全局范围内的特定部分。这导致我们的函数名称与页面上附加脚本中定义的其他函数相冲突的可能性降低了。
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
Advantages
优势
why is the Module pattern a good choice? For starters, it's a lot cleaner for developers coming from an object-oriented background than the idea of true encapsulation, at least from a JavaScript perspective.
为什么模块模式是一个好的选择?首先,对于来自面向对象背景的开发人员来说,它比真正封装的概念要干净得多,至少从JavaScript的角度来看是这样。
Secondly, it supports private data - so, in the Module pattern, public parts of our code are able to touch the private parts, however the outside world is unable to touch the class's private parts.
其次,它支持私有数据——因此,在模块模式中,代码的公共部分能够触及私有部分,但是外部世界无法触及类的私有部分。
Disadvantages
缺点
The disadvantages of the Module pattern are that as we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used.
模块模式的缺点是,当我们以不同的方式访问公共和私有成员时,当我们希望改变可见性时,我们实际上必须对每个成员使用的位置进行更改。
We also can't access private members in methods that are added to the object at a later point. That said, in many cases the Module pattern is still quite useful and when used correctly, certainly has the potential to improve the structure of our application.
我们也不能访问在稍后添加到对象的方法中的私有成员。这就是说,在许多情况下,模块模式仍然非常有用,并且在正确使用时,当然有可能改进我们的应用程序的结构。
The Revealing Module Pattern
显示模块的模式
Now that we're a little more familiar with the module pattern, let’s take a look at a slightly improved version - Christian Heilmann’s Revealing Module pattern.
现在我们对模块模式更熟悉了,让我们看一下稍微改进的版本——Christian Heilmann的揭示模块模式。
The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables.He also disliked the Module pattern’s requirement for having to switch to object literal notation for the things he wished to make public.
揭示模块的模式出现了,因为Heilmann对他不得不重复主对象的名称的事实感到沮丧,因为我们想从另一个公共方法调用一个公共方法或者访问公共变量。他也不喜欢模块模式的要求,即必须切换到对象文字符号,以实现他想要公开的东西。
The result of his efforts was an updated pattern where we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.
他的努力的结果是一个更新的模式,我们只需在私有范围内定义所有的函数和变量,然后返回一个匿名对象,并指向我们希望公开的私有功能。
An example of how to use the Revealing Module pattern can be found below
下面是一个如何使用揭示模块模式的示例。
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Advantages
优势
This pattern allows the syntax of our scripts to be more consistent. It also makes it more clear at the end of the module which of our functions and variables may be accessed publicly which eases readability.
此模式允许脚本的语法更加一致。它还使模块的末尾更加清晰,我们的函数和变量可以被公开访问,从而简化可读性。
Disadvantages
缺点
A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.
这种模式的缺点是,如果一个私有函数引用一个公共函数,那么如果需要一个补丁,那么公共函数就不能被覆盖。这是因为私有函数将继续引用私有实现,而模式并不适用于公共成员,只适用于函数。
Public object members which refer to private variables are also subject to the no-patch rule notes above.
引用私有变量的公共对象成员也要遵守上面的无补丁规则说明。
#17
6
I'm 7 years late to the party, but did quite a bit of work around this 8 years ago:
我已经迟到7年了,但8年前我做了很多工作:
- http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
- http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
- http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
- http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
It is important to be able to easily and efficiently create multiple nested namespaces to keep a complex web application organized and manageable, while respecting the JavaScript global namespace (preventing namespace pollution), and with not clobbering any existing objects in the namespace path while doing so.
很重要的一点是,能够轻松和高效地创建多个嵌套的名称空间,以保持复杂的web应用程序的组织和管理,同时尊重JavaScript全局名称空间(防止名称空间污染),并且在这样做的同时不阻塞名称空间路径中的任何现有对象。
From the above, this was my circa-2008 solution:
以上是我的circa-2008解决方案:
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
This isn't creating a namespace, but provides a function for creating namespaces.
这不是创建名称空间,而是为创建名称空间提供了一个函数。
This can be condensed to a minified one-liner:
这可以浓缩成一个小型的一行:
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
Example of use:
使用的例子:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
Or, as one statement:
或者,正如一个声明:
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
Either is then executed as:
要么被执行为:
com.example.namespace.test();
If you don't need support for legacy browsers, an updated version:
如果您不需要对遗留浏览器的支持,则需要更新版本:
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
Now, I'd be leery of exposing namespace
to the global namespace itself. (Too bad the base language doesn't provide this for us!) So I'd typically use this myself in a closure, such as:
现在,我希望将名称空间暴露给全局名称空间本身。(糟糕的是,基本语言并不能为我们提供这些!)所以我通常会在闭包中使用它,比如:
(function(){
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
const ns = namespace("com.ziesemer.myApp");
// Optional:
ns.namespace = ns;
// Further extend, work with ns from here...
}());
console.log("\"com\":", com);
In a larger application, this only needs to be defined once at the beginning of a page load (for client-based web apps). Additional files can then reuse the namespace function if kept (included as "optional" in the above). At worst, if this function is re-declared a few times - it's only a few lines of code, and less if minified.
在更大的应用程序中,这只需要在页面加载开始时定义一次(对于基于客户机的web应用程序)。如果保留了名称空间函数(包括在上面的“可选”),则可以重用其他文件。在最坏的情况下,如果这个函数被重新声明了几次——它仅仅是几行代码,如果缩小了就更少了。
#18
#19
3
My favorite pattern has become lately this:
我最喜欢的模式是:
var namespace = (function() {
// expose to public
return {
a: internalA,
c: internalC
}
// all private
/**
* Full JSDoc
*/
function internalA() {
// ...
}
/**
* Full JSDoc
*/
function internalB() {
// ...
}
/**
* Full JSDoc
*/
function internalC() {
// ...
}
/**
* Full JSDoc
*/
function internalD() {
// ...
}
})();
Of course, return can be at the end, but if only function declarations follow it, it's much easier to see what's the namespace all about, and what API is exposed.
当然,返回可以在最后,但是如果只有函数声明遵循它,那么就更容易看到名称空间的全部内容,以及所暴露的API。
The pattern of using function expressions in such cases results in not being able to know what methods are exposed without going over the entire code.
在这种情况下,使用函数表达式的模式导致无法知道哪些方法在不经过整个代码的情况下被公开。
#20
1
Quite a follow-up of Ionuț G. Stan's answer, but showing the benefits of uncluttered code by using var ClassFirst = this.ClassFirst = function() {...}
, which takes advantage of JavaScript's closure scoping for less namespace cluttering for classes in the same namespace.
后续Ionuțg·斯坦的回答,但显示的好处使用var ClassFirst =这整洁的代码。ClassFirst = function(){…},它利用了JavaScript的闭包,为相同名称空间中的类提供了更少的命名空间。
var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
Output:
输出:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
#21
1
I like Jaco Pretorius' solution, but I wanted to make the "this" keyword a bit more useful by pointing it to the module/namespace object. My version of skillet:
我喜欢Jaco Pretorius的解决方案,但我希望通过将这个关键字指向模块/名称空间对象,使这个关键字更有用。我的版本的锅:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);
#22
1
We can use it independently in this way:
我们可以这样独立地使用它:
var A = A|| {};
A.B = {};
A.B = {
itemOne: null,
itemTwo: null,
};
A.B.itemOne = function () {
//..
}
A.B.itemTwo = function () {
//..
}
#23
0
If using a Makefile you can do this.
如果使用Makefile,您可以这样做。
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;
// clientfile.js
billy.bob();
I prefer to use a Makefile anyway once I get to about 1000 lines because I can effectively comment out large swaths of code by removing a single line in the makefile. It makes it easy to fiddle with stuff. Also, with this technique the namespace only appears once in the prelude so it's easy to change and you don't have to keep repeating it inside the library code.
我更倾向于使用Makefile,因为我可以使用大约1000行代码,因为我可以通过删除Makefile中的一行代码来有效地注释掉大量代码。这让你很容易摆弄东西。而且,使用这种技术,名称空间只会在序曲中出现一次,因此很容易更改,而且您不必在库代码中不断重复它。
A shell script for live development in the browser when using a makefile:
使用makefile时浏览器中实时开发的shell脚本:
while (true); do make; sleep 1; done
Add this as a make task 'go' and you can 'make go' to keep your build updated as you code.
将此添加为make任务'go',您可以'make go'以保持您的构建更新为您的代码。
#24
0
I've written another namespacing library that works a bit more like packages / units do in other languages. It allows you to create a package of JavaScript code and the reference that package from other code:
我编写了另一个命名空间库,它更像其他语言中的包/单元。它允许您创建一个JavaScript代码包,并从其他代码中引用该包:
File hello.js
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
File Example.js
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
Only the second file needs to be included in the page. Its dependencies (file hello.js in this example) will automatically be loaded and the objects exported from those dependencies will be used to populate the arguments of the callback function.
只有第二个文件需要包含在页面中。其依赖项(文件你好。在这个示例中,将自动加载并从这些依赖项中导出的对象将用于填充回调函数的参数。
You can find the related project in Packages JS.
您可以在包JS中找到相关的项目。
#25
0
My habit is to use function myName() as property storage, and then var myName as "method" holder...
我的习惯是使用函数myName()作为属性存储,然后使用var myName作为“方法”holder…
Whether this is legitimate enough or not, beat me! I am relying on my PHP logic all the time, and things simply work. :D
不管这是否合理,打我吧!我一直依赖于我的PHP逻辑,而事情只是简单地工作。:D
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log('Object creation failed!')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
if (this !==) myobject . fname1 ();其他myObj.fName2();
You can also do it in a 'vice versa' way to check before object creation which is much better:
你也可以用“反之亦然”的方式来检查对象的创建,这是更好的方法:
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log('myObj failed!');
debugger;
}
else
myObj.init();
Reference to this: JavaScript: Creating Object with Object.create()
引用这个:JavaScript:用Object.create()创建对象。
#26
0
In JavaScript there are no predefined methods to use namespaces. In JavaScript we have to create our own methods to define NameSpaces. Here is a procedure we follow in Oodles technologies.
在JavaScript中没有预定义的方法来使用名称空间。在JavaScript中,我们必须创建自己的方法来定义名称空间。这是我们在Oodles技术中遵循的一个过程。
Register a NameSpace Following is the function to register a name space
注册一个名称空间是注册一个名称空间的函数。
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
To register a Namespace just call the above function with the argument as name space separated by '.'
(dot). For Example Let your application name is oodles. You can make a namespace by following method
要注册一个名称空间,只需将上面的函数命名为“分隔的名称空间”。”(点)。例如,让您的应用程序名称为oodles。您可以通过以下方法创建名称空间。
registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
Basically it will create your NameSpaces structure like below in backend:
基本上,它将在后端创建您的名称空间结构:
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
In the above function you have register a namespace called "oodles.HomeUtilities"
and "oodles.GlobalUtilities"
. To call these namespaces we make an variable i.e. var $OHU
and var $OGU
.
在上面的函数中,您已经注册了一个名为“oodles”的名称空间。HomeUtilities”和“oodles.GlobalUtilities”。要调用这些名称空间,我们创建一个变量,即var $OHU和var $OGU。
These variables are nothing but an alias to Intializing the namespace. Now, Whenever you declare a function that belong to HomeUtilities
you will declare it like following:
这些变量只不过是命名空间的别名。现在,当你声明一个属于homeuti的函数时,你会声明如下:
$OHU.initialization = function(){
//Your Code Here
};
Above is the function name initialization and it is put into an namespace $OHU
. and to call this function anywhere in the script files. Just use following code.
上面是函数名初始化,它被放入一个名称空间$OHU中。在脚本文件的任何地方调用这个函数。用代码。
$OHU.initialization();
Similarly, with the another NameSpaces.
类似地,使用另一个名称空间。
Hope it helps.
希望它可以帮助。