当您不知道属性是变量还是函数时,javascript的设计模式

时间:2011-07-20 04:06:45

标签: javascript function object

我的对象中的许多属性可能是值或返回值的函数。访问值与调用函数(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();方法,但因为我必须为每个属性写一个新函数而不是值或函数,我认为最好使用foo.Get(foo.bar);保持干燥的方法。如果您不能推荐更好的解决方案,我仍然希望听到您对这两种方法的反馈。

感谢。

3 个答案:

答案 0 :(得分:1)

在这种情况下,我通常使用全局实用程序将每个可能是函数的属性转换为一个,然后始终调用函数而不是访问属性:

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());

答案 1 :(得分:1)

我不知道这是否适合您 - 您可能需要考虑Javascript getter / setter函数。例如:

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

通过这种方式,您可以像访问任何媒体一样访问bar,也就是说,通过评估foo.bar

当然这可能会引入一些浏览器兼容性问题 - Javascript getter / setter是相当新的;它们被添加到2009年的第5版ECMA-262中。

答案 2 :(得分:0)

在这种情况下,某些库所做的是通过getset方法进行所有访问,而不是直接调用任何内容。

obj.get( “条”) obj.set(“bar”,4);

然后,在这些方法的实现中,您可以检查基础类型,并直接返回值或调用它的函数。在set方法中,如果它是一个函数,你可以传递arguments数组,以便在需要时在setter上允许任意数量的参数。

这也允许子类在需要时覆盖这些方法,因为你现在基本上有setter和getter。显然,由于您放弃了直接设置和检索属性的清洁度,因此在使用这些方面会有一些牺牲。但是,你要求设计模式,所以这是一个。

YUI库使用此方法。

这比原生的setter和getter的优势在于它适用于任何浏览器版本(具有上述缺点)。