最近我看到以下代码在javascript中创建了一个类:
var Model.Foo = function(){
// private stuff
var a, b;
// public properties
this.attr1 = '';
this.attr2 = '';
if(typeof Model.Foo._init === 'undefined'){
Model.Foo.prototype = {
func1 : function(){ //...},
func2 : function(){ //... },
//other prototype functions
}
}
Model.Foo._init = true;
}
// Instantiate and use the class as follows:
var foo = new Model.Foo(); foo.func1();
我想_init变量用于确保我们不再重新定义原型。此外,我觉得代码更具可读性,因为我将所有内容放在一个功能块中(所以在oop-speak中,所有属性和方法都在一个地方)。 您是否看到上述代码存在任何问题?如果我需要在一个大项目中创建大量的类,使用这种模式的任何陷阱?
答案 0 :(得分:2)
这是一个奇怪的Javascript模式,我永远不会用它来开发面向对象的JS代码。首先,如果Model.Foo._init === 'undefined'
不是字符串true
,Model.Foo._init
永远不会评估为'undefined'
;因此,代码
Model.Foo.prototype = {
func1 : function(){ /* ... */},
func2 : function(){ /* ... */},
//other prototype functions
}
除非该条件成立,否则将不会运行。 (也许作者想要添加typeof
,就像typeof Model.Foo._init === 'undefined'
一样?我不知道。)
解决您对“确保我们不再定义原型”的担忧,这已经实现了:
Model.Foo = function() {
// private stuff
var a, b;
// public properties
this.attr1 = '';
this.attr2 = '';
};
Model.Foo.prototype = {
func1 : function() { /* ... */},
func2 : function() { /* ... */}
//,other prototype functions
};
// Instantiate and use the class as follows:
var foo = new Model.Foo();
foo.func1();
如果你没有使用框架,那就是我推荐的。
基本上,你的问题的答案是:如果你使用这种非标准模式进行开发,那么其他程序员,甚至几个月后你自己也会发现很难扩展和使用它。
答案 1 :(得分:1)
看起来似乎不必要的复杂。您需要遵守纪律,以便在原型扩展的实现中不使用Model.Foo的任何参数或局部变量。奇怪的是覆盖整个.prototype对象,而不仅仅是添加单个成员。为什么不以正常的方式做到这一点?
var Model.Foo = function(){
// private stuff
var a, b;
// public properties
this.attr1 = '';
this.attr2 = '';
}
Model.Foo.prototype.func1 = function(){ //...};
Model.Foo.prototype.func2 = function(){ //... };
替代允许每个实例成员变量私有
var Model.Foo = function(){
// private stuff
var a, b;
// public properties
this.attr1 = '';
this.attr2 = '';
this.func1 = function(){ //...};
this.func2 = function(){ //... };
}
答案 2 :(得分:0)
有些事情可能很麻烦:
Foo.prototype
设置为一个简单的对象,使用此模式无法扩展任何内容。Foo.prototype
中定义的函数中使用,而这些函数只能运行一次。这有点混乱,网上有更好的细节/例子就是这样做。
答案 3 :(得分:0)
以下示例说明了我个人随着时间的推移开发的模式。
它利用作用域来允许私有字段和方法。
有关详细讨论,请查看JavaScript class patterns
Employee = (function(){
// private static field
var staticVar;
// class function a.k.a. constructor
function cls()
{
// private instance field
var name = "";
var self = this;
// public instance field
this.age = 10;
// private instance method
function increment()
{
// must use self instead of this
self.age ++;
}
// public instance method
this.getName = function(){
return cls.capitalize(name);
};
this.setName = function(name2){
name = name2;
};
this.increment = function(){
increment();
};
this.getAge = function(){
return this.age;
};
}
// public static field
cls.staticVar = 0;
// public static method
cls.capitalize = function(name){
return name.substring(0, 1).toUpperCase() +
name.substring(1).toLowerCase();
};
// private static method
function createWithName(name)
{
var obj = new cls();
obj.setName(cls.capitalize(name));
return obj;
}
return cls;
})();
john = new Employee();
john.setName("john");
mary = new Employee();
mary.setName("mary");
mary.increment();
alert("John's name: " + john.getName() + ", age==10: "+john.getAge());
alert("Mary's name: " + mary.getName() + ", age==11: "+mary.getAge());