我使用CoffeeScript创建一个类并构建一个私有方法,但我的代码感觉很糟糕。
如下例所示,首先我用=定义方法然后我被迫在要使用的部分上使用call方法。但这似乎是一个愚蠢的解决方法,所以我想知道是否有更清洁的解决方案。
class Human
constructor: (@name, @height, @weight) ->
_realWeight = ->
@weight
answerWeight: ->
console.log(_realWeight.call(@) - 5)
$ ->
ken = new Human('Ken', 165, 70)
ken.answerWeight()
答案 0 :(得分:1)
没有
只有一种方法可以在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
仍能正常工作(在某种程度上它可以正常工作)。
WeakMaps
(对于IE 11或其破坏)。有一个垫片,但它不能完全填充。无论垫片是否足够接近,都必须打电话给你。