OO Javascript构造函数模式:neo
我观看了道格拉斯克罗克福德关于Javascript中的优秀部分的演讲,并且我的眼睛被打开了。 他说,有一点像“Javascript是唯一的语言,好的程序员相信他们可以有效地使用它,而不需要学习它。” 然后我意识到,我就是那个人。
在那次演讲中,他发表了一些对我来说非常令人惊讶和有见地的发言。 例如,JavaScript是这个星球上最重要的编程语言。 或者它是这个星球上最流行的语言。 而且,它以许多严肃的方式被打破。
他对我所做的最令人惊讶的表述是“新的危险”。 他不再使用它了。 他也不使用this
。
他为Javascript中的构造函数提供了一个有趣的模式,它允许私有和公共成员变量,并且不依赖于new
,也不依赖this
。 它看起来像这样:
// neo-classical constructor
var container = function(initialParam) {
var instance = {}; // empty object
// private members
var privateField_Value = 0;
var privateField_Name = "default";
var privateMethod_M1 = function (a,b,c) {
// arbitrary
};
// initialParam is optional
if (typeof initialParam !== "undefined") {
privateField_Name= initialParam;
}
// public members
instance.publicMethod = function(a, b, c) {
// because of closures,
// can call private methods or
// access private fields here.
};
instance.setValue = function(v) {
privateField_Value = v;
};
instance.toString = function(){
return "container(v='" + privateField_Value + "', n='" + privateField_Name + "')";
};
return instance;
}
// usage
var a = container("Wallaby");
WScript.echo(a.toString());
a.setValue(42);
WScript.echo(a.toString());
var b = container();
WScript.echo(b.toString());
编辑 :代码更新切换到小写类名称。
这种模式已经从Crockford早期的使用模式演变而来。
问题:你使用这种构造函数模式吗? 你觉得这可以理解吗? 你有更好的吗?
这看起来像模块模式的非单例版本,通过利用JavaScript的“闭包”可以模拟私有变量。
我喜欢它(有点......)。 但是我并没有真正看到以这种方式完成的私有变量的优点,特别是当它意味着添加(初始化后)任何新方法都无法访问私有变量时。
另外,它没有利用JavaScript的原型模型。 所有的方法和属性都必须在构造函数被调用时进行初始化 - 如果存储在构造函数原型中的方法不会发生。 事实是,使用传统的构造函数/原型模式要快得多! 你真的认为私有变量使性能命中值得吗?
这种模型对于模块模式是有意义的,因为它只被初始化一次(创建一个伪单身),但我不太确定它在这里是否有意义。
你使用这种构造函数模式吗?
不,虽然我确实使用它的单例变体,模块模式......
你觉得这可以理解吗?
是的,它的可读性和清晰度很高,但我不喜欢把所有内容都包含在构造函数中的想法。
你有更好的吗?
如果你真的需要私有变量,那就坚持下去吧。 否则,只需使用传统的构造函数/原型模式(除非您分享Crockford对new
/ this
组合的恐惧):
function Constructor(foo) {
this.foo = foo;
// ...
}
Constructor.prototype.method = function() { };
其他与Doug关于该主题的观点有关的类似问题:
我避免这种模式,因为大多数人发现阅读起来比较困难。 我通常遵循两种方法:
如果我只有一件东西,那么我使用匿名对象:
var MyObject = {
myMethod: function() {
// do something
}
};
对于我使用标准JavaScript原型继承的一个以上的东西
var MyClass = function() {
};
MyClass.prototype.myMethod = function() {
// do something
};
var myObject = new MyClass();
(1)阅读,理解和写作要容易得多。 (2)在有多个对象时更有效。 Crockford的代码每次都会在构造函数中创建一个新的函数副本。 封闭也有更难调试的缺点。
虽然你失去了真正的私有变量,但是你可以用_
作为约定给应该成为私有成员的前缀加个前缀。
this
是在JavaScript中公认的难题,但可以利用周围进行加工.call
和.apply
正确设置它。 我也经常使用var self = this;
创建一个闭包变量来作为this
在成员函数中定义的函数。
MyClass.prototype.myMethod = function() {
var self = this;
// Either
function inner1() {
this.member();
}
inner1.call(this);
// Or
function inner2() {
self.member();
}
inner2();
};
你使用这种构造函数模式吗?
不
你觉得这可以理解吗?
是的,它非常直接。
你有更好的吗?
我还没有看过这个话题,但我很快就会谈到。 在那之前,我没有看到使用new
和this
的危险, this
是为什么:
没有听过他的观点,我只能假设,他建议从由于性质这样的事情避而远之this
,以及它是如何容易,这取决于执行的特定方法(直接在原来的对象或上下文改变作为回调等)。 作为一名教育工作者,他可能会教会回避这些关键词,因为大部分人并没有意识到和缺乏经验的开发人员在不考虑该语言的本质的情况下擅长JavaScript。 对于有经验的开发谁是密切与熟悉的语言,我不相信这是必须避免的语言,授予它的灵活性,数量惊人的(这是避免类似的事情完全不同的这一特点with
)。 所有这一切说,我现在会看。
无论如何,当不使用某种支持dojo.declare
继承的框架(如dojo.declare
),或者在编写独立于框架的对象时,我现在采取以下方法。
定义:
var SomeObject = function() {
/* Private access */
var privateMember = "I am a private member";
var privateMethod = bindScope(this, function() {
console.log(privateMember, this.publicMember);
});
/* Public access */
this.publicMember = "I am a public member";
this.publicMethod = function() {
console.log(privateMember, this.publicMember);
};
this.privateMethodWrapper = function() {
privateMethod();
}
};
用法 :
var o = new SomeObject();
o.privateMethodWrapper();
bindScope
是类似于Dojo的dojo.hitch
或Prototype的Function.prototype.bind
的dojo.hitch
Function.prototype.bind
。
上一篇: OO Javascript constructor pattern: neo
下一篇: Are there legitimate uses for JavaScript's "with" statement?