带有函数原型的 Javascript 命名空间声明
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7137860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript namespace declaration with function-prototype
提问by Johnny Sterlak
I know, this is often discussed. But after searching around like someone out of the 19th century, I need some advice. I have no problem by declaring a "namespace", but when it comes to a prototype.foo function, I stuck. I found a way, but I don't like it:
我知道,这经常被讨论。但是在像 19 世纪的人一样四处寻找之后,我需要一些建议。声明“命名空间”没有问题,但是当涉及到prototype.foo 函数时,我被卡住了。我找到了一种方法,但我不喜欢它:
Namespace = {}
Namespace.obj = function() {
this.foo="bar";
}
Namespace.obj.prototype.start = function() {
this.foo="fubar";
}
blah = new Namespace.obj();
blah.start();
Now, since I'm a little neurotic in case of scripting, I would like to have something like this:
现在,由于我在编写脚本时有点神经质,我想要这样的东西:
Namespace = {
obj: function() {
this.foo="bar";
},
obj.prototype.start: function(tabinst) {
this.foo="fubar";
}
}
...
But then it throws an error: "Uncaught SyntaxError: Unexpected token ."
但随后它会抛出一个错误:“未捕获的 SyntaxError: Unexpected token 。”
I know, this is cosmetic, but I think that there has to be a better method of declaring a "namespace" containing a class and prototype functions.
我知道,这是装饰性的,但我认为必须有更好的方法来声明包含类和原型函数的“命名空间”。
回答by Amjad Masad
The way I would do it is using the "Module pattern".
You basically encapsulate all your "Module" logic in a self executing function that would return an object having your classes, functions, variables etc... Think of the return value as exposing your Module API.
我的做法是使用“模块模式”。
您基本上将所有“模块”逻辑封装在一个自执行函数中,该函数将返回一个包含您的类、函数、变量等的对象......将返回值视为暴露您的模块 API。
Namespace = (function () {
/** Class obj **/
var obj = function () {
this.foo = 'bar';
};
obj.prototype = {
start: function () {
this.foo = 'fubar';
}
};
/** Class obj2 **/
var obj2 = function () {
this.bar = 'foo'
};
obj2.prototype = {
start: function () {
this.bar = 'barfoo';
},
end: function () {
this.bar = '';
}
};
return {
obj : obj,
obj2: obj2
};
})();
var o = new Namespace.obj()
o.start()
In order to further encapsulate the "obj" class methods and constructor we could do the following:
为了进一步封装“obj”类方法和构造函数,我们可以执行以下操作:
/** Class obj **/
var obj = (function () {
/** class Constructor **/
var obj = function () {
this.foo = 'bar';
};
/** class methods **/
obj.prototype = {
start: function () {
this.foo = 'fubar';
}
};
return obj;
})();
There is also an important feature that comes for free using this pattern, which is "Private variables", consider the following:
使用此模式还有一个免费的重要功能,即“私有变量”,请考虑以下事项:
/** Class Foo **/
var Foo = (function () {
// Private variables
var private_number = 200
/** class Constructor **/
var Foo = function () {
this.bar = 0;
};
/** class methods **/
Foo.prototype = {
add: function () {
this.bar += private_number;
}
};
return Foo;
})();
foo = new Foo();
alert(foo.bar); // 0
foo.add();
alert(foo.bar);// 200
alert(foo.private_number) //undefined
回答by Pantelis
Yes because, you cannot use this type of chaining in an object declaration
是的,因为您不能在对象声明中使用这种类型的链接
obj.prototype or obj.something here, because the language sees obj as a non-object value. You can fake such an effect like this
obj.prototype 或 obj.something 在这里,因为语言将 obj 视为非对象值。你可以像这样伪造这样的效果
Namespace = {};
Namespace.obj =function() {
this.foo="bar";
};
Namespace.obj.prototype.start = function(tabinst) {
this.foo="fubar";
};
console.log( Namespace.obj.prototype );
(see this fiddle http://jsfiddle.net/WewnF/)
(见这个小提琴http://jsfiddle.net/WewnF/)
EDIT: Wow, I just noticed that what I said was already within the question. I 'm so sorry did not notice that sooner... Well the way you described yourself is the correct method of achieving this.
编辑:哇,我刚刚注意到我所说的已经在问题中了。我很抱歉没有早点注意到......好吧,你描述自己的方式是实现这一目标的正确方法。
Otherwise you can re-write your code like this - but is not exactly what you 're after and won't work the same (since obj won't be a function itself and you will have to call its main function like this obj.main(); )
否则,您可以像这样重新编写代码 - 但不完全是您所追求的,并且不会以相同的方式工作(因为 obj 本身不是一个函数,您将不得不像这样调用它的主函数 obj.主要的(); )
Namespace = {
obj: {
main : function() {
this.foo="bar";
},
prototype : {
start: function(tabinst) {
this.foo="fubar";
}
}
}
}
EDIT 2: See this fiddle http://jsfiddle.net/NmA3v/1/
编辑 2:看到这个小提琴http://jsfiddle.net/NmA3v/1/
Namespace = {
obj: function() {
this.foo="bar";
},
prototype: {
obj : {
start : function( hi ) {
alert( hi );
}
}
},
initProto : function(){
for( var key in Namespace )
{
if( key !== "prototype" )
{
for( var jey in Namespace.prototype[ key ] )
Namespace[ key ].prototype[ jey ] = Namespace.prototype[ key ][ jey ];
}
}
}
}
Namespace.initProto();
console.log( Namespace.obj);
var test = new Namespace.obj();
test.start( "Hello World" );
This will have the exact same effect. Explanation : we are declaring our objects as normal properties-functions, and then use a master prototype object which containers objects with the same names as above, for example for each Namespace.obj, there is also a Namespace.prototype.obj which contains the functions we want to add in the prototype chain.
这将产生完全相同的效果。说明:我们将我们的对象声明为普通的属性函数,然后使用一个主原型对象,其中包含与上面相同名称的对象,例如对于每个 Namespace.obj,还有一个 Namespace.prototype.obj 包含我们要添加到原型链中的函数。
then with namespace.protoInit(), we iterate through all properties - and extract the functions from the Namespace.prototype[ key ] and add them to Namespace[ key ].prototype - succesfully extending the prototype object! A bit unorthodox, but works!
然后使用 namespace.protoInit(),我们遍历所有属性 - 并从 Namespace.prototype[ key ] 中提取函数并将它们添加到 Namespace[ key ].prototype - 成功扩展原型对象!有点非正统,但有效!
回答by Zarne Dravitzki
Just for kicks and to expand on the answer above. A bit more object notation oriented based on nested namespace
只是为了踢球并扩展上面的答案。基于嵌套命名空间的更多面向对象符号
var NS = {};
// Class List
NS.Classes = {
Shape: (function(){
// Private
var whateveryouwishboss = false;
// Public
var Shape = function(x,y,w,h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
};
Shape.prototype = {
draw: function(){
//... Im on prototype Shape
}
}
return Shape;
})(),
Person: (function(){
//....
})()
}
/////// Let the games begin
var rect = new NS.Class.Shape(0,0,10,10);
rect.draw()