对象的成员都是 public 公共成员。任何函数都可以访问、修改或者删除这些成员。有两种主要的途径给新的对象加入成员:
这个技术一般用来初始化公共实例变量。构造器的this 变量是用来向对象添加成员的。
function Container(param) { this.member = param; }
这样,如果我们构造一个新的对象
var myContainer = new Container('abc');
那么myContainer.member 就会包含'abc' 。
这个技巧一般用来添加公共方法。当一个成员被检索且没有在对象中发现的时候,那么它就会从对象构造器的 prototype 成员中去获取它。这个原型机制可用来实现继承。 它也保存内存。要为一个构造器生成的所有对象加入一个方法,将函数加入构造器的prototype 中:
Container.prototype.stamp = function (string) { return this.member + string; }
这样,我们可以调用这个方法
myContainer.stamp('def')
它会返回'abcdef' .
私有Private 成员要由构造器生成。构造器中的普通的var 变量和参数都成为私有成员。
function Container(param) { this.member = param; var secret = 3; var self = this; }
这个构造器有三个私有实例变量:param , secret , 和 self 。它们被附加到了对象上,但它们无法从外部访问,同时它们也无法被这个对象的公共方法所访问。 他们只对私有成员可见。私有方法则是构造器内部的函数。
function Container(param) { function dec() { if (secret > 0) { secret -= 1; return true; } else { return false; } } this.member = param; var secret = 3; var self = this; }
私有方法 dec 检查 secret 实例变量。如果它大于0 ,就减少secret 的大小并返回 true 。否则它返回 false 。这个可以限制对象使用三次。
按照惯例,我们给出一个私有的 self 参数。这个可以令对象对私有方法可见。 这种做法是因为ECMAScript Language Specification 中的一个错误,这个错误令 this 不能正确地对内部函数设置。
私有方法无法被公共方法调用。要令私有方法有用,我们需要引入一种特权方法。
一个特权A privileged 方法可以访问私有的变量和方法,同时它对公共域可见。也可以删除或替换一个特权方法,但不能改变它。
特权方法是用 this 在构造器中分配的。
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var self = this;
this.service
= function () {//特权方法
if (dec()) {
return self.member;
} else {
return null;
}
};
}
service 就是一个特权方法。前三次调用会返回'abc' 。 之后 ,它会返回 null 。service 调用的私有的 dec 方法,而 dec 又访问了私有的 secret 变量。service 对其它的对象和方法是可见的,但不能直接访问私有成员。
这种公共、私有和特权成员的模式是可行的原因是由于JavaScript有 closure 闭包。这个意味着一个内部的函数总是可以访问这个函数外部的变量和参数,甚至在外部的函数返回之后。这是这个语言的一个极其强大的特性。目前没有哪本关于JavaScript编程的书展示了如何发掘这个特性。大多数都没有提到。
私有和特权成员只能在对象构造的时候生成。公共成员可以在任意时刻添加。