我正在尝试将对象链接到其他对象以编写Node模块。这是我到目前为止(受this answer启发):
'use strict'
// Composable prototype object
var parent = {
publicVar: 1,
doSomething() {
return externalMethod(this.publicVar) + 10
}
}
// Composable prototype object
var child = {
doSomethingChild() {
return this.publicVar + 20
}
}
// an external method
function externalMethod(arg) {
return arg
}
// the parent factory
function Parent() {
let privateVar = 2
return Object.assign({
getPrivate() {
return privateVar
}
}, parent)
}
// the child factory
function Child() {
let privateVar = 4
let parent = Parent() // call to the Parent factory
return Object.assign(parent, child, {
getPrivateChild() {
return privateVar
}
})
}
// Node export
module.exports = {
Parent: Parent(),
Child: Child()
}
稍后,我将需要以下模块:
Parent = require('./my-module').Parent
Child = require('./my-module').Child
Parent.getPrivate() // 2
Parent.doSomething() // 11
Child.getPrivateChild() // 4
Child.doSomethingChild() // 21
恐怕使用OLOO可能会有更优雅的方法。我主要担心的是,我认为我应该在Child工厂中执行
let parent = Object.create(Parent)
,但是如果这样做,它将无法正常工作。因此,1)我是否缺少某些东西,2)可以重构吗?
最佳答案
与单祖先类继承相比,您绝对应该更喜欢组合(包括mixins),因此您处于正确的轨道上。也就是说,JavaScript没有私有(private)属性,因为您可能从其他语言中了解到它们。我们使用闭包来保护JS中的数据隐私。
对于具有真实数据保密性(通过闭包)的可组合原型(prototype),您正在寻找的是功能mixins ,这些功能接受一个对象并返回添加了新功能的对象。
但是,在我看来,使用可组合工厂(例如stamps)进行函数继承通常是更好的做法。 AFAIK,Stampit是可组合工厂中使用最广泛的实现。
标记是可组合的工厂函数,可根据其描述符返回对象实例。邮票有一种称为.compose()
的方法。调用.compose()
方法时,将使用当前图章作为基础创建新图章,该图章由作为参数传递的可组合对象列表组成:
const combinedStamp = baseStamp.compose(composable1, composable2, composable3);
可组合标记是图章或POJO(普通的旧JavaScript对象)图章描述符。
.compose()
方法兼用作图章的描述符。换句话说,描述符属性被附加到图章.compose()
方法,例如stamp.compose.methods
。可组合描述符(或仅描述符)是一个元数据对象,其中包含创建对象实例所需的信息。
描述符包含:
methods
—将添加到对象的委托(delegate)原型(prototype)中的一组方法。 properties
-一组将通过分配添加到新对象实例的属性。 initializers
-将按顺序运行的函数数组。标记详细信息和参数传递给初始化程序。 staticProperties
—一组静态属性,将通过分配给图章来复制。 基本问题如“我如何继承特权方法和私有(private)数据?”和“继承层次结构有哪些好的替代方案?”是许多JavaScript用户的绊脚石。
让我们使用
init()
库中的compose()
和stamp-utils
同时回答这两个问题。compose(…composables: [...Composable]) => Stamp
接受任意数量的可组合内容并返回一个新戳记。 init(…functions: [...Function]) => Stamp
采用任意数量的初始化函数并返回新的标记。 首先,我们将使用闭包来创建数据隐私:
const a = init(function () {
const a = 'a';
Object.assign(this, {
getA () {
return a;
}
});
});
console.log(typeof a()); // 'object'
console.log(a().getA()); // 'a'
它使用函数作用域来封装私有(private)数据。请注意,必须在函数内部定义getter才能访问闭包变量。
这是另一个:
const b = init(function () {
const a = 'b';
Object.assign(this, {
getB () {
return a;
}
});
});
这些
a
不是错别字。关键是要证明a
和b
的私有(private)变量不会冲突。但这是真正的享受:
const c = compose(a, b);
const foo = c();
console.log(foo.getA()); // 'a'
console.log(foo.getB()); // 'b'
WAT?是的您只是同时从两个源继承了特权方法和私有(private)数据。
使用可组合对象时,应遵循一些经验法则:
myNewObject
需要featureA
,featureB
和featureC
,因此:myNewFactory = compose(featureA, featureB, featureC); myNewObject = myNewFactory()
。请注意,myNewObject
不是featureA
,featureB
等的实例,而是实现,使用或包含这些功能的实例。 如果您遵循这些准则,您的邮票和混币将不受常见继承问题的影响,例如脆弱的基类问题, gorilla /香蕉问题,重复性必要性问题等。
关于javascript - 如何在JS中使用行为委托(delegate)(OLOO)定义私有(private)变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42611606/