看以下这段代码:
<html>
<body>
<script>
class1 = function()
{
// 私有属性
var m_first = 1;
var m_second = 2;
// 私有方法
function method1()
{
alert(m_first);
}
var method2 = function()
{
alert(m_second);
}
// 构建函数
{
method1();
method2();
}
}
var o = new class1();
// 提示未定义
alert(o.m_first);
// 错误:对象不支持此属性或方法
o.method1();
</script>
</body>
</html>
这段代码其实是在介绍JavaScript如何建立一个私有变量与私有方法。这个不是大问题。要关注的是,进入类后,类的私有方法就可以使用类的私有变量了,一层层的,有意思。而类的私有方法使用全局变量也是正常,没有悬念。类的公用方法使用类的私有变量或全局变量亦没有问题。
var i=2;
……
this.method3=function () //类的公用方法
{
alert (m_first + ":" + i); //使用类的私有变量与全局变量
}
……
这里有列出两种构建私有函数的方法(常规函数定义与匿名函数赋给变量),事实上还会有更多,只要构建函数的方法都可以拿来一试,如:new Function
但为什么会“第二种方式更灵活一些”?
如果全局变量与私有变量重名怎么办?这个问题好象很变态,如果我是主管的话,会把这种程序员拿来骂一顿,(编程的命名体系也要检讨一下)。只当学术研究,实际走一下,还真的不好研究:
var m_first=1;
class1 = function()
{
var m_first = 2;
function method1()
{
var m_first=3;
alert(window.m_first + "?" + this.m_first + "?" + m_first + "?" +
method1.caller.m_first);
想把1?2?3显示出来,就是搞不定。
构建函数,该段代码把除声明变量、定义函数的语句之外的执行语句用 { } 括起来,“这样做虽然没有必要,但是代码看上去更加清晰。”,认同!以前认为是杂乱无章的代码,现在有一个这么时髦的名称,那当然高兴啊。
这里,原作者有提醒一点,构造函数应该放在整个类定义的最后部分,因为那时,该定义的函数都定义好了,或该赋初值的变量也赋好了(变量的定义在任何地方都可以)。这里又有个问题:如果函数是用普通的直接定义,其实构造函数放哪都一样,如果函数是用匿名函数赋给变量的方式定义,则就要执行过才行。在VS的单步跟踪时,你就会发现,如果是语句:
var m_first = 1;
调试器会走过,而如果是语句:
var m_first;
则调试器就不会理会。同样,如果是语句:
var method2 = function () { ... }
调试器会走过(一下子整段走过,而不是具体执行其中的代码),如果是语句:
function method1() { ... }
调试器也不理会。从这一点来看,我就觉得var method2=function() { ... }的这种定义方法并不好。调试时还要走过这句话。
因此,如果你的代码都是定义型的语句,那构建函数其实是可以放在类首的,而且我也觉得这样更好。
此外作者为了避免在构建函数中创建多余的私有变量,建议把构建函数单独划出一个普通函数来,这个建议也不错,如下代码就很容易造成误解
<html>
<body>
<script>
var i=1;
class1 = function()
{
// constructor
{
for (var i=0; i<5; i++)
{
document.write("OK");
}
method1();
}
function method1()
{
alert(i); //最后提示什么,全局变量1还是局部变量5?答案是:5
}
}
var o = new class1();
</script>
</body>
</html>
不过函数的名称,我想用constructor会不会造成误解?因为constructor已经有意义的了。并且它太长了一点。
<html>
<body>
<script>
class1 = function()
{
function constructor()
{
document.write("OK");
}
constructor();
function method1()
{
alert("TT");
}
}
var o = new class1();
alert(o.constructor); //这里会不会造成误解
</script>
</body>
</html>
所以我想用_cs固定作为构建函数。本也有想用类名,但那更容易误解,而_+类名作为构建函数,则会因为类改名(不稳定阶段,我经常这样干),构建函数也要跟着改名。_cs可以理解为ConStructor,也可以理解为Class Start,会打cs的人更不会忘,前面加一个下划线更显示它的特殊性。好,就这样。
开始随想,我们在C#中使用的类与其实例,是不是也是像这样,构建一个实例其实是让程序有一个机会去执行一遍类的相关代码。
第二个,这段代码的作者也有个习惯,私有变量用m_来开头,而VB6中的生成控件向导也是这个习惯,因此也变成我的习惯了。
第三个,提示类的私有变量,系统其实不会严重错误而中止,而是提示“undefined”,而执行一个私有方法,系统就会严重出错。显然前者与我们普通的编程有冲突,也隐藏着潜在的问题(难怪我的JavaScript程序错误那么多),如果有一种方法保证如果使用私有变量,系统也会弹出严重错误就好了(当然,更好的是,在没有执行前就告诉你这些地方严重错误)。
最后,作者提示了一个最后,class1是用匿名函数的方式来定义的,没有带var,说明它是一个全局类,我不太想用匿名函数,因此改为普通函数来定义。这时,我才发现用普通函数定义的,与匿名函数赋给变量的区别点之一:后者可以让函数为全局函数(但再想一下,这不一定是件好事)。
天啊,这段代码我写了这么多,始料未及(?)