重读《javascript高级程序设计》第三版笔记 私有变量
私有变量
“严格来讲,JavaScript 中没有私有成员的概念;所有对象属性都是公有的。不过,倒是有一个私有 变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量。”
通过下面的例子,我们来解读上面这一句话:
function animal() {
var name = 'Joe' //私有变量
this.species = 'Husky' //公有变量
}
var dog = new animal()
console.log(dog.species) // Husky
我们可以发现,外部是可以直接访问species这个变量的,但无法访问name,那么该如何访问内部的私有变量?我们可以
function animal() {
var name = 'Joe' //私有变量
this.species = 'Husky' //公有变量
this.say = function () {
return name
}
}
var dog = new animal()
console.log(dog.say()) // 输出Joe
有权访问私有变量和私有函数的公有方法称为特权方法(privileged method),在上面的例子中,say这个函数,就是该对象的特权方法。
静态私有变量
我们先来看一个例子:
(function(){
var name = "";
Person = function(value){
name = value;
};
Person.prototype.getName = function(){
return name;
};
Person.prototype.setName = function (value){
name = value;
};
})();
var person1 = new Person("Nicholas");
console.log(person1.getName()); //"Nicholas"
person1.setName("Greg");
console.log(person1.getName()); //"Greg"
var person2 = new Person("Michael");
console.log(person1.getName()); //"Michael"
console.log(person2.getName()); //"Michael"
var person3 = new Person('youngbye');
console.log(person1.getName()); //youngbye
console.log(person2.getName()); //youngbye
console.log(person3.getName()); //youngbye
这个模式创建了一个私有作用域,并在其中封装了一个构造函数及相应的方法。在自执行的函数中,Person由于没有使用var定义,所以它成为了一个全局变量,外部是可以访问Person。 其次,getName和setName是在原型上定义,符合典型的原型模式。 Person 构造函数与 getName()和 setName()方法一样,都有权访问私有变量 name。 在这种模式下,变量 name 就变成了一个静态的、由所有实例共享的属性。在一个实例上调 用 setName()会影响所有实例。而调用 setName()或新建一个 Person 实例都会赋予 name 属性一个 新值。结果就是所有实例都会返回相同的值。
## 小总结
- 即使 JavaScript 中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公 有方法可以访问在包含作用域中定义的变量。
- 有权访问私有变量的公有方法叫做特权方法。
- 可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强 的模块模式来实现单例的特权方法。