更好的方法来调用私有方法

时间:2016-02-15 03:48:09

标签: coffeescript

我使用CoffeeScript创建一个类并构建一个私有方法,但我的代码感觉很糟糕。

如下例所示,首先我用=定义方法然后我被迫在要使用的部分上使用call方法。但这似乎是一个愚蠢的解决方法,所以我想知道是否有更清洁的解决方案。

class Human
  constructor: (@name, @height, @weight) ->

  _realWeight = ->
    @weight

  answerWeight: ->
    console.log(_realWeight.call(@) - 5)

$ ->
  ken = new Human('Ken', 165, 70)
  ken.answerWeight()

1 个答案:

答案 0 :(得分:1)

TL; DR

没有

更长的答案

只有一种方法可以在javascript / coffeescript:closures中拥有真正的私有数据。

首先,让我们考虑一些替代方案:

<强>符号

因为符号是唯一的,所以它们可用于创建伪私有数据: 如果您对其键入的符号有引用,则只能访问该属性:

foo = Symbol('I am unique')
bar = {}
bar[foo] = "I am almost private"

无法访问foo的代码无法轻松访问bar的{​​{1}}属性,但Object.getOwnPropertySymbols除外。所以不容易打破,但易碎。

<强>下划线

典型的命名约定表示以下划线为前缀或后跟的属性/方法是“私有”,外部调用者不会使用它们。但是,那个隐私&#39;不会以任何方式由运行时强制执行。

所以我们来谈谈闭包。

简单关闭示例

makeFoo = (something) -> getSomething: -> something
foo = makeFoo(3)
foo.something      # undefined
foo.getSomething() # 3

现在除了调用方法之外,没有办法获取传递给构造函数的参数。这种模式虽然在coffeescript中略显优雅,但仍然有点蹩脚。大量重复的功能对象。仅仅getSomething并没有那么糟糕,但添加了一堆方法,它会变得很难看。此外,JIT编译器通常不像foo = new Foo()那样容易优化。幸运的是,ES 2015拯救了:

高级关闭示例

Foo = null
do ->
  privateData = new WeakMap()
  getSomething = -> privateData.get(this)
  Foo = class Foo
    constructor: (something) -> privateData.set(this, something)
    getSomething: getSomething


foo = new Foo(3)
foo.something              # undefined
foo.getSomething()         # 3
new Foo(42).getSomething() # 42
foo instanceof Foo         # true

现在,Foo的所有实例共享getSomething的一个副本,而不是每个人都获得自己的副本。弱图隐藏在由IIFE创建的闭包中,并且因为弱点&#39;当实例被垃圾收集时,WeakMap的一部分私有数据也将被收集。您现在也可以享受编译器优化new创建的对象的好处。最后但并非最不重要的是,instanceof仍能正常工作(在某种程度上它可以正常工作)。

Further reading.

Even More reading

注意

并非所有浏览器都支持

WeakMaps(对于IE 11或其破坏)。有一个垫片,但它不能完全填充。无论垫片是否足够接近,都必须打电话给你。