2015-02-27 2 views
2

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

foo.width(500).height(250).margin({left:5,right:10}); 

Я мог бы, очевидно, создать определение функции, как:

margin(value) { 
    this.config.margin = value; 
    return this; 
} 

Но что, если бы я хотел, чтобы быть в состоянии поддерживать вышеуказанную функцию сцепления, но также прямого назначения, как:

foo.margin = {left:5,right:10}; 

Я мог бы добавить эту поддержку, добавив сеттер, как:

Но у вас не может быть сеттер и функция, которые идут под тем же именем, и, по-видимому, сеттер работает только с литеральной операцией присваивания, а определение функции работает только с плавным API-интерфейсом.

Есть ли способ иметь синтаксически изящный способ с JS ES6?


Я включил скрипку, которая демонстрирует рабочий пример как оперативных, так и литеральных операторов присваивания. Единственная проблема? Мне пришлось прибегать к использованию другой именованной подписи, которая увеличивает поверхность API ... если возможно, я бы хотел этого избежать.

http://www.es6fiddle.com/i6o0jscx/

+0

Вопрос в том, почему вы добавляете свойства, подобные тем же именам, что и функция? Я предполагаю, что это невозможно, и что вы должны просто изменить 'foo.config.margin = 'something'' вместо – adeneo

+0

@adeneo Я не уверен, что я следую. Я считаю, что это довольно распространенная практика на других языках. Вы хотите, чтобы настройка свойства private/protected выполнялась только через сеттер, и вы хотите, чтобы к ним обращались как операторы свободного, так и буквенного присваивания. – ken

+1

@ken Нет, в других языках нет обычной практики иметь свойства, которые иногда бывают как свойства, иногда и подобные методы. В большинстве случаев это одно или другое. Это то, чего вы пытаетесь достичь здесь, и поэтому у вас проблемы. – JLRishe

ответ

2

Если вы готовы использовать дополнительные два символа, чтобы получить значения свойств, то вы можете сделать это:

export class Foo { 
    constructor() { 
    this.config = { 
     width:500, 
     height: 400 
    }; 
    } 

    get width() { 
    return function(value) { 
     if (arguments.length) { 
     this.config.width = value; 
     return this; 
     } 
     return this.config.width; 
    }; 
    } 
    set width(value) { 
    this.config.width = value; 
    } 
} 

let foo = new Foo(); 
console.log(foo.width()); 
foo.width = 600; 
console.log(foo.width()); 
console.log(foo.width(250).width()); 

В основном, геттер возвращает функцию, которая устанавливает значение, если оно вызывается с аргументами, или возвращает значение, если оно вызывается без аргументов. Это похоже на API jQuery, который обеспечивает .text() и .html() и многое другое, но дает дополнительную возможность назначения напрямую этому свойству. Я бы не рекомендовал этого, потому что это не смущает возможность делать foo.width = 5;, но не var w = foo.width;, но я не вижу хорошего способа полностью выполнить то, что вы пытаетесь сделать.

http://www.es6fiddle.com/i6o14n4b/

+0

Хорошо спасибо @JLRishe. Это было «приятно иметь», но я могу жить без него, если это невозможно. – ken

+0

Мне просто очень нравится подход к интерфейсу Fluent, когда у вас есть большое количество свойств для установки, и все же предпочтет литеральные задания, когда будут одноразовые. – ken

+1

@ken Ну, как я уже сказал, возможно иметь обе эти вещи, но компромисс заключается в том, что вы должны использовать '()' для извлечения значения. Но если вы не согласны с подходом Fluent, я бы предложил сделать это. Это более гибкие и литеральные задания действительно не имеют большого преимущества. – JLRishe

1

Вы можете иметь и другое. Вам просто нужно придерживаться соглашений об именах:

class Thing { 
    constructor() { 
    this._property = 0; 
    } 

    get property() { 
    return this._property; 
    } 

    set property(property) { 
    this._property = property; 
    } 

    setProperty(property) { 
    this.property = property; 
    return this; 
    } 
} 

Таким образом, вы можете получить торт и съесть его тоже.

+0

Да, я использовал этот подход раньше, и я думаю, что соглашение об именах довольно ясное. Тем не менее, я решил в большинстве случаев пойти так или иначе, но не оба. Спасибо за предложение, хотя ... это было хорошо. – ken

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