我喜欢闭包,因为你可以从他们那里制作一个API,但是你不能拥有多个实例。
var Person = (function () {
// private properties and methods
var Constr, name;
// public API
Constr = function (n) {
name = n;
};
Constr.prototype.sayName = function(){return name;};
return Constr;
}());
var person1 = new Person('Foo');
var person2 = new Person('Bar'); //New values will overwrite the name because of the closure.
console.log(person1.sayName()); //Bar
console.log(person2.sayName()); //Bar
是否有其他方法可以使用原型来访问私有成员并创建不同的实例?
答案 0 :(得分:2)
如果你真的想将构造函数和成员用作私有,那么你可以这样做
var Person = function(my_name) {
// private properties and methods
var Constr, name;
// public API
Constr = function(n) {
name = n;
};
Constr.prototype.sayName = function() {
return name;
};
return new Constr(my_name);
};
注意:强>
但这效率不高,因为我们每次创建Constr
的对象时都必须创建Person
构造函数。
这使得从Constr
/ Person
继承不可能,因为Constr
无法从外部访问,Person
的原型为空。
console.log(Person.prototype); // {}
我认为,并非所有变量都是私有的。所以,你可以拥有私人会员,比如这个
var Person = function(my_name) {
// private properties and methods
var name = my_name;
// public API
this.getName = function() {
return name;
}
this.setName = function(newName) {
name = newName;
}
};
Person.prototype.printName = function() {
console.log(this.getName());
}
var person1 = new Person('Foo');
var person2 = new Person('Bar');
console.log(person1.getName()); // Foo
console.log(person2.getName()); // Bar
console.log(Person.prototype); // { printName: [Function] }
person1.printName();
person2.printName();
答案 1 :(得分:1)
我认为未来的方式是Object.defineProperties,它与通常与HTML5兼容的浏览器兼容(IE9 +,最值得注意的是;请参阅es5-shim以获得最佳的回填功能)。
有了这个,你可以定义看起来像属性(而不是函数)的只读getter,并且不要每次都填充原型继承或创建一个新的构造函数:(JSFiddle here)
// name is read-only, but only modern browsers (ie 9+)
function Person(attributes) {
Object.defineProperties(this, {
name: {value: attributes.name}
})
}
person1 = new Person({name: 'Foo'});
person2 = new Person({name: 'Bar'});
console.log(person1.name) // Foo
console.log(person2.name) // Bar
或者,与其他人评论的内容类似,您可以执行以下操作以获得更好的浏览器兼容性,同时保持原型正确性和只读API:
// read-only-ish, but better browser compatibility
function Person(attributes) {
this._name = attributes.name
}
Person.prototype.name = function() { return this._name }
person1 = new Person({name: 'Foo'});
person2 = new Person({name: 'Bar'});
console.log(person1.name()) // Foo
console.log(person2.name()) // Bar
答案 2 :(得分:0)
您可以在此处减少构造函数的数量,并在每次调用new Person(name)
时创建一个新的公共接口:
function Person(name)
{
// return public api that closes over 'name'
return {
sayName: function() {
return name;
}
};
}
您返回的公共界面将不再是Person
的实例,请注意这一特定方法。