Javascript 闭包和多个实例
我喜欢闭包,因为可以从闭包中生成API,但不能有多个实例,这很糟糕Javascript 闭包和多个实例,javascript,Javascript,我喜欢闭包,因为可以从闭包中生成API,但不能有多个实例,这很糟糕 是否有其他方法可以使用原型访问私有成员并创建不同的实例?如果您真的想将构造函数和成员用作私有成员,那么您可以这样做 var Person = function(my_name) { // private properties and methods var Constr, name; // public API Constr = function(n) { name = n;
是否有其他方法可以使用原型访问私有成员并创建不同的实例?如果您真的想将构造函数和成员用作私有成员,那么您可以这样做
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);
};
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();
注意:
Person
对象时,我们都必须创建Constr
构造函数Constr
/Person
继承成为不可能,因为Constr
无法从外部访问,并且Person
的原型为空
console.log(Person.prototype); // {}
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);
};
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();
您可以在此处减少构造函数的数量,并在每次调用
newperson(name)
时创建一个新的公共接口:
function Person(name)
{
// return public api that closes over 'name'
return {
sayName: function() {
return name;
}
};
}
您返回的公共界面将不再是
Person
的实例,这是一个需要记住的特殊方法。我认为未来的方式是,它与通常与HTML5兼容的浏览器兼容(最显著的是IE9+,请参阅以获得最佳的回填效果)
这样,您就可以定义看起来像属性(而不是函数)的只读getter,并且不会破坏原型继承或每次都创建一个新的构造函数:()
或者,与其他人的评论类似,您可以执行以下操作以提高浏览器兼容性,同时保持原型正确性和只读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
它们是私有的,但不是每个实例所独有的。不用担心JS中的封装,这样做很好。_name,因此下划线是一种表示“私有”的约定。原型方法是共享的,因此它们不能基于每个对象访问变量@elclanrs:在大多数情况下,解决方案应该是足够的。否则,您将放弃原型方法,并为每个实例提供自己的方法。@CookieMonester但公共方法可以通过特权方法访问私有成员,因此这不是世界末日,只是效率稍低一点。:-)@RobG:通过“public”,你是在专门谈论原型方法吗?如果是这样的话,是的,这是真的,但我看不出这有什么意义,因为您仍然需要基于每个实例创建方法。那么,为什么原型方法要调用每个实例的方法,而不是直接调用每个实例的方法呢?@cookiemonster-“但我看不出这有什么意义”事实上,这就是为什么大多数走这条路的人最终只是“公开”的原因特权方法可以模拟getter和setter,但同样,它们修改的属性也可能是公共的。是的,使用特权方法获取和设置私有成员(可能还有其他东西)的值是很常见的,这样继承的方法就可以使用它们。但正如埃尔克兰斯所说,有时候,只要你遵守纪律,最终付出的努力是不值得的(但在团队中并不总是如此)。了解了后者,似乎没有其他办法。谢谢你展示了非正统的选项!太棒了。您将如何使用
Object.defineProperties
inside Person访问/覆盖名称?@Tek取决于您的意图。您可以再次调用Object.defineProperties(还没有尝试,只是有意义),或者如果您只是想要一个标准的getter/setter,您可以将writeable:true
添加到{value:attributes.name}