请注意,由Bondye 提供的链接提供的模块模式不包含私有实例属性。它适用于函数属性,因为函数不会因每个实例而改变,但对于值属性的工作有点不可预测,如下面的代码所示:
var module = (function () {
// private variables and functions
var foo = 'bar';
// constructor
var module = function (name) {
// instance variables
this.name=name;
};
// prototype
module.prototype = {
constructor: module,
something: function () {
// notice we're not using this.foo
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
};
// return module
return module;
})();
var m1 = new module("m1");
var m2 = new module("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: new value
正如您在最后一行代码中看到的那样,m1 和 m2 实例共享一个名为 foo 的私有变量(所有实例都将指向相同的值)。
我可以从Bondye 发布的另一个链接中看出,很难在 JavaScript 中模拟私有性,您可以考虑使用命名约定来指示属性是私有的。您可以使用 google 闭包编译器之类的东西并注释您的 JS 代码以指示私有;但是使用闭包编译器有它自己的缺点(除非与闭包编译器兼容并且代码必须采用某种格式才能在高级模式下编译,否则无法编译使用的库)。
另一种选择是完全抛弃原型(至少对于使用私有属性的所有内容)并将所有内容放在构造函数的主体中(或使用返回对象的函数)。
// function returning an object
function makeObj(name){
// private vars:
var foo = "bar";
return {
name:name,
something:function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
}
var m1=makeObj("m1");
var m2=makeObj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
// constructor with everything in the constructor's body:
function Obj(name){
// private vars:
var foo = "bar";
this.name=name;
this.something=function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
Obj.prototype.someOtherFunction=function(){
// anything here can't access the "private" variables
}
var m1=new Obj("m1");
var m2=new Obj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
使用私有实例值可能会遇到的另一个问题是它们只能在实例中访问。当您想要克隆一个对象并在您的对象中定义一个克隆函数来创建一个新实例时,您必须编写公共访问器函数来设置私有值,因为您不能像在Java 私有字段中那样直接设置它们。
有关在此处使用构造函数的更多信息:原型继承 - 编写