从每个实例都有一个私有闭包的模块导出一个 class,但它的原型链仍然可以扩展?
Export a class from a module where each instance has a private closure, but it's prototype chain can still be extended?
f.e。假设我有
function foo() {
var privateVariable = "foo"
return class Foo {
constructor() {
// do something with privateVariable
}
}
}
export default foo
所以我将导出 returns 和 class 的函数,然后 class 的每个实例都会有一个闭包,从函数被调用以获取 class.然后我可以做
import foo from "Foo"
var instance = new (foo())()
每个实例都由返回的 class 构成,因此每个实例的原型都有一个私有闭包(是的,这不是最有效的,因为每次都会返回一个新的 class 定义)。问题是扩展 class 意味着从 Foo 扩展的每个实例将共享一个闭包,f.e.
var Foo = foo() // get a new class definition
class Bar extends Foo {
// ...
}
现在每次我创建 new Bar()
时它的原型都是 Foo,但是每个 class 扩展 Foo 原型将共享相同的私有闭包(基本上私有变量现在是 static) 因为不是每次都获取新的 Foo 定义。
我如何使 Foo 可扩展以便每个 new Bar()
的 Foo 原型都有一个私有闭包?
编辑 2015 年 2 月 7 日 12:53am: 有趣的是,我想出了自己的解决方案,这恰好类似于使用 WeakMap 的公认答案,除了这只是一张地图,并不弱:
//
// --- PrivateManager.js
//
function PrivateManager() { // singleton
this.instances = []
this.instanceData = {}
this.currentId = 0
}
PrivateManager.prototype.__register = function(instance, instanceDatum) {
if (this.instances.indexOf(instance) === -1) {
this.instances[this.currentId] = instance
this.instanceData[this.currentId] = instanceDatum
this.currentId++
}
}
PrivateManager.prototype.__getMethod = function(desiredMethod) {
return this[desiredMethod]
}
//
// --- Person.js
//
function PersonPrivateManager() {
var mngr = this
this.getName = function() {
return mngr.instanceData[mngr.instances.indexOf(this)].name
}
}
PersonPrivateManager.prototype = new PrivateManager()
var privateMngr = new PersonPrivateManager()
function Person(name) {
privateMngr.__register(this, {
name: name
})
}
Person.prototype.getName = privateMngr.__getMethod("getName")
//
// --- app.js
//
var person1 = new Person('Bentra')
console.log(person1.getName()) // Bentra
console.log(person1.name) // undefined
var person2 = new Person('Amadar')
console.log(person2.getName()) // Amadar
console.log(person2.name) // undefined
console.log(person1.getName === person2.getName) // true, references to the same function, no memory waste as far as duplicate functions go.
缺点是它不会像 WeakMap 那样自动进行垃圾回收。这是一个冲动的解决方案。它可以被修改以模仿 WeakMap 的清洁器 API,减去垃圾收集。
将 WeakMap 放入 Foo 的模块顶级范围,并将私有变量分配给以实例为键的弱映射。
这样只有在该模块中定义的函数才能访问它,使其有效地私有化。
为您的 Bar
类 做同样奇怪的事情:
import foo from "Foo"
function bar() {
var Foo = foo();
return class Bar extends Foo {
constructor() {
}
}
}
export default bar
f.e。假设我有
function foo() {
var privateVariable = "foo"
return class Foo {
constructor() {
// do something with privateVariable
}
}
}
export default foo
所以我将导出 returns 和 class 的函数,然后 class 的每个实例都会有一个闭包,从函数被调用以获取 class.然后我可以做
import foo from "Foo"
var instance = new (foo())()
每个实例都由返回的 class 构成,因此每个实例的原型都有一个私有闭包(是的,这不是最有效的,因为每次都会返回一个新的 class 定义)。问题是扩展 class 意味着从 Foo 扩展的每个实例将共享一个闭包,f.e.
var Foo = foo() // get a new class definition
class Bar extends Foo {
// ...
}
现在每次我创建 new Bar()
时它的原型都是 Foo,但是每个 class 扩展 Foo 原型将共享相同的私有闭包(基本上私有变量现在是 static) 因为不是每次都获取新的 Foo 定义。
我如何使 Foo 可扩展以便每个 new Bar()
的 Foo 原型都有一个私有闭包?
编辑 2015 年 2 月 7 日 12:53am: 有趣的是,我想出了自己的解决方案,这恰好类似于使用 WeakMap 的公认答案,除了这只是一张地图,并不弱:
//
// --- PrivateManager.js
//
function PrivateManager() { // singleton
this.instances = []
this.instanceData = {}
this.currentId = 0
}
PrivateManager.prototype.__register = function(instance, instanceDatum) {
if (this.instances.indexOf(instance) === -1) {
this.instances[this.currentId] = instance
this.instanceData[this.currentId] = instanceDatum
this.currentId++
}
}
PrivateManager.prototype.__getMethod = function(desiredMethod) {
return this[desiredMethod]
}
//
// --- Person.js
//
function PersonPrivateManager() {
var mngr = this
this.getName = function() {
return mngr.instanceData[mngr.instances.indexOf(this)].name
}
}
PersonPrivateManager.prototype = new PrivateManager()
var privateMngr = new PersonPrivateManager()
function Person(name) {
privateMngr.__register(this, {
name: name
})
}
Person.prototype.getName = privateMngr.__getMethod("getName")
//
// --- app.js
//
var person1 = new Person('Bentra')
console.log(person1.getName()) // Bentra
console.log(person1.name) // undefined
var person2 = new Person('Amadar')
console.log(person2.getName()) // Amadar
console.log(person2.name) // undefined
console.log(person1.getName === person2.getName) // true, references to the same function, no memory waste as far as duplicate functions go.
缺点是它不会像 WeakMap 那样自动进行垃圾回收。这是一个冲动的解决方案。它可以被修改以模仿 WeakMap 的清洁器 API,减去垃圾收集。
将 WeakMap 放入 Foo 的模块顶级范围,并将私有变量分配给以实例为键的弱映射。 这样只有在该模块中定义的函数才能访问它,使其有效地私有化。
为您的 Bar
类 做同样奇怪的事情:
import foo from "Foo"
function bar() {
var Foo = foo();
return class Bar extends Foo {
constructor() {
}
}
}
export default bar