2016-02-15 8 views
2

Я использую CoffeeScript для создания класса и создания частного метода, но мой код выглядит kludgy.Лучший способ вызова частного метода

Как и в приведенном ниже примере, сначала я определяю метод с =, а затем я вынужден использовать метод вызова для используемой части. Но это похоже на клоническое обходное решение, поэтому я хочу знать, есть ли более чистое решение.

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

    _realWeight = -> 
    @weight 

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

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

В JavaScript нет частной собственности, поэтому их нет в CoffeeScript. У вас действительно есть * функция *, которая определена в рамках функции «Человек». Использование 'Function.prototype.call' или' Function.prototype.apply' - это все, что вы можете сделать. –

ответ

1

TL; DR

No.

Longer Ответ

Существует только один способ иметь действительно личные данные в JavaScript/CoffeeScript: затворы.

Во-первых, давайте рассмотрим некоторые варианты:

Символы

Поскольку символы являются уникальными, они могут быть использованы для создания псевдо-частных данных: вы можете получить доступ только свойство, если у вас есть ссылка на символ его ключом к:

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

код, который не имеет доступа к foo не могут легко добраться до этого имущества bar за исключением Object.getOwnPropertySymbols. Так что нелегко сломать, но пробить.

Подчеркивает

Типичного соглашения об именах говорит, что свойства/методы префикс или следуют подчеркивания являются «частными», они не должны быть использованы внешним абонентом. Тем не менее, что «конфиденциальность» никак не выполняется во время выполнения.

Так что давайте поговорим о закрытии.

Простой пример Закрытие

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

Теперь нет никакого способа, чтобы получить в параметре передается конструктору, кроме как для вызова метода. Этот образец, немного более элегантный в coffeescript, все еще немного хромает. Множество дублированных объектов функции. Не так уж плохо для всего getSomething, но добавьте кучу методов, и он становится уродливым. Кроме того, как правило, не так легко оптимизируется компилятором JIT, как foo = new Foo(). К счастью, ES 2015 на помощь:

Advanced Closure Пример

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, и из-за «слабой» части WeakMap, когда экземпляр получает сбор мусора, частные данные также будут. Теперь вы также можете воспользоваться преимуществами оптимизации компилятора new созданных объектов. И последнее, но не менее важное: instanceof все еще работает должным образом (в той мере, в какой он когда-либо работает правильно).

Further reading.

Even More reading

Примечание

WeakMaps не поддерживаются во всех браузерах (для IE его 11 или спадов). Существует прокладка, но она не может быть полностью заполнена. Независимо от того, подходит ли прокладка, достаточно позвонить, который вам нужно будет сделать.

Смежные вопросы