javascript - 如何在JS中使用行为委托(delegate)(OLOO)定义私有(private)变量?

标签 javascript ecmascript-6 stampit.js

我正在尝试将对象链接到其他对象以编写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不是错别字。关键是要证明ab的私有(private)变量不会冲突。

    但这是真正的享受:
    const c = compose(a, b);
    
    const foo = c();
    console.log(foo.getA()); // 'a'
    console.log(foo.getB()); // 'b'
    

    WAT?是的您只是同时从两个源继承了特权方法和私有(private)数据。

    使用可组合对象时,应遵循一些经验法则:
  • 组成不是类继承。不要尝试为is-a关系建模,也不要以 parent / child 关系来思考事物。相反,请使用基于功能的思维。 myNewObject需要featureAfeatureBfeatureC,因此:myNewFactory = compose(featureA, featureB, featureC); myNewObject = myNewFactory()。请注意,myNewObject不是featureAfeatureB等的实例,而是实现,使用或包含这些功能的实例。
  • Stamps和mixins不应该互相了解。 (无隐式依赖)。
  • Stamps和mixins应该很小。引入尽可能少的新属性。
  • 进行合成时,您可以而且应该有选择地仅继承所需的 Prop ,并重命名 Prop 以避免碰撞。
  • 只要有可能(大多数时候),都倾向于使用模块进行代码重用。
  • 首选用于域模型和状态管理的功能编程。避免共享可变状态。
  • 优先使用高阶函数和高阶组件,而不是任何种类的继承(包括mixin或图章)。

  • 如果您遵循这些准则,您的邮票和混币将不受常见继承问题的影响,例如脆弱的基类问题, gorilla /香蕉问题,重复性必要性问题等。

    关于javascript - 如何在JS中使用行为委托(delegate)(OLOO)定义私有(private)变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42611606/

    相关文章:

    javascript - stampit.js 初学者需要一些指导

    javascript - jquery 不够快,无法更改左上角的值

    javascript - 遍历 dom 从具有 id 和 class 的单击元素获取

    javascript - Android CloudRail 品牌网站失败 - "Unexpected token )"(community.js 第 18 行)

    javascript - 有什么方法可以在 express 中使用 next() 有条件地跳过中间件?

    JavaScript - 解构对象中的默认值作为参数传递给箭头函数

    javascript - 标记的模板文字的 TemplateObject 数组是否被其领域弱引用?

    javascript - 合并数组中的两个对象