Шаблон дизайна для JavaScript, когда вы не знаете, будет ли свойство переменной или функцией - PullRequest
1 голос
/ 20 июля 2011

Многие свойства в моих объектах могут быть либо значением, либо функцией, которая возвращает значение. Доступ к значению отличается от вызова функции (foo; vs foo ();). В настоящее время я использую следующий подход. Кто-нибудь может порекомендовать что-нибудь лучше?

var foo = {
    bar: function(){
        return 1;
    },
    // bar: 1, // bar may also be a standard value
    GetBar: function(){
        return $.isFunction(this.bar) ? this.bar() : this.bar;
    },
    Get: function(property){
        return $.isFunction(property) ? property() : property;
    }
}
foo.GetBar();//1
foo.Get(foo.bar);//1

Я сейчас использую foo.GetBar (); подход, но поскольку мне нужно написать новую функцию для каждого свойства, а не van или значение, или функцию, я думаю, что лучше всего использовать foo.Get (foo.bar); подход, чтобы держать его сухим. Если вы не можете порекомендовать лучшее решение, я все равно хотел бы услышать ваши отзывы по обоим предоставленным методам.

Спасибо.

Ответы [ 3 ]

1 голос
/ 20 июля 2011

Я не знаю, подходит ли вам этот вариант - вы можете рассмотреть функции получения / установки Javascript. Например:

var foo = {
    get bar() {
        return 1;
    }
};

Таким образом, вы можете получить доступ к bar так же, как и к любому свойству, то есть, оценив foo.bar.

Конечно, это может создать некоторые проблемы с совместимостью с браузерами - Javascript getters / setters довольно новы; они были добавлены в 5-е издание ECMA-262 в 2009 году.

1 голос
/ 20 июля 2011

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

function functor(v) {
    return typeof v == "function" ? v : function() { return v; };
};

unknown = functor(unknown);
var myVar = unknown();

В этом примере это выглядит немного глупо, но достаточно просто включить его в объект, подобный вашему:

var foo = {
    bar: "some value or function",
    get: function(key) {
        return functor(this[key])();
    }
};

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

function Foo(height, width) {
    this.height = functor(height);
    this.width = functor(width);
}

// make a new object with a fixed height and a width dependent
// on the current window size
var foo = new Foo(10, function() { return $(window).width() - 100; } );
// now always assume functions
console.log(foo.height(), foo.width());
0 голосов
/ 20 июля 2011

В этом случае некоторые библиотеки делают так, чтобы весь доступ осуществлялся с помощью get и set методов, а не вызывал что-либо напрямую.

obj.get ("bar") obj.set ("bar", 4);

Затем в вашей реализации этих методов вы можете проверить базовый тип и либо вернуть значение напрямую, либо вызвать его функцию.В методе set, если это функция, вы можете передать массив arguments, чтобы разрешить произвольное количество аргументов в установщике, если это необходимо.

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

Библиотека YUI использует этот метод.

Преимущество этого по сравнению с собственными установщиками и получателями заключается в том, что это будет работать в любой версии браузера (с указанными выше недостатками).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...