var Person = (
function ()
{
var checkNo =
function (no)
{
if (!no.constructor ==
"string" || no.length !=
4)
throw new Error(
"学号必须为4位");
};
var times =
0;
return function (no, name, age)
{
console.log(times++);
var no , name , age;
this.setNo =
function (no) //私有方法
{
checkNo(no);
this._no = no;
};
this.getNo =
function ()
{
return this._no;
}
this.setName =
function (name)
{
this._name = name;
}
this.getName =
function ()
{
return this._name;
}
this.setAge =
function (age)
{
this._age = age;
}
this.getAge =
function ()
{
return this._age;
}
this.setNo(no);
this.setName(name);
this.setAge(age);
}
})();
Person.prototype = {
constructor: Person,
toString:
function ()
{
return "no = " +
this._no +
" , name = " +
this._name +
" , age = " +
this._age;
}
};
var p1 =
new Person(
"0001",
"小平果",
"22");
var p2 =
new Person(
"0002",
"abc",
"23");
var p3 =
new Person(
"0003",
"aobama",
"24");
console.log(p1.toString());
console.log(p2.toString());
console.log(p3.toString());
上述代码,js引擎加载完后,会直接执行Person = 立即执行函数,然后此函数返回了一个子函数,这个子函数才是new Person所调用的构造函数,又因为子函数中保持了对立即执行函数中checkNo(no) ,times的引用,(很明显的闭包)所以对于checkNo和times,是所有Person对象所共有的,创建3个对象后,times分别为0,1,2 。这种方式的好处是,可以使Person中需要复用的方法和属性做到私有且对象间共享。
这里的私用成员和特权成员仍然被声明在构造器。但那个构造器却从原来的普通函数变成了一个内嵌函数,并且被作为包含它的函数的返回值给变量Person。这就创建了一个闭包,你可以把静态的私用成员声明在里面。位于外层函数声明之后的一对空括号很重要,其作用是代码一载入就立即执行这个函数。这个函数的返回值是另一个函数,它被赋给Person变量,Person因此成了一个构造函数。在实例华Person时,所调用的这个内层函数。外层那个函数只是用于创建一个可以用来存储静态成员的闭包。
在本例中,checkno被设计成为静态方法,原因是为Person的每个实例都生成这个方法的一个新副本毫无道理。此外还有一个静态属性times,其作用在于跟踪Person构造器的总调用次数。