【问题标题】:Design pattern for javascript when you don't know if a property will be a variable or a function当您不知道属性是变量还是函数时的 javascript 设计模式
【发布时间】:2011-07-20 04:06:44
【问题描述】:

我的对象中的很多属性可能是一个值,也可能是一个返回值的函数。访问一个值不同于调用一个函数(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);保持干燥的方法。如果您不能推荐更好的解决方案,我仍然希望听到您对所提供的两种方法的反馈。

谢谢。

【问题讨论】:

    标签: javascript function object


    【解决方案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());
    

    【讨论】:

      【解决方案2】:

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

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

      通过这种方式,您可以像访问任何属性一样访问bar,即通过评估foo.bar

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

      【讨论】:

      • 我很想用这个,可惜我需要支持IE。
      【解决方案3】:

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

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

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

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

      YUI 库使用这种方法。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-03
        • 2021-05-16
        • 2012-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多