扩展/覆盖jQuery对象文字方法 - 超出范围问题

时间:2016-07-08 18:30:55

标签: javascript jquery oop jquery-plugins

我在编写jQuery插件方面经验很少,使用JavaScript设计模式的经验也很少,所以请耐心等待。

我正在编写jQuery扩展中使用单例模式。这工作正常,但我希望能够扩展/覆盖我的单例对象的方法和属性。

为了实现这一点,我有一个主var self = {}对象,在运行时,它将包含一个属性对象文字和一个方法对象文字。它们各自的对象文字的各个属性和方法将被设置为默认值或者传入一个选项参数。

这也有效,直到您传入尝试访问self.propertiesself.methods的方法。因为self仅在单例对象中定义而不是我想要传入的对象文字,所以在传递任何内容之前都会抛出JavaScript错误。

为了更好地理解这一点,下面我创建了一个非常类似于我想要做的完整示例。

;(function ( $, window, document, undefined ) {
    $.extend({
        MyObject : function(options) {

            // enfore singleton pattern
            $.MyObject = function() {
                if(typeof $.MyObject != 'undefined') { // if an instance exists
                    console.log('$.MyObject is a singleton - original instance returned');
                    return $.MyObject; // return original instance
                }
                else return this; // else, return this instance
            };

            var self = {},
            defaults = {
                properties : {
                    prop : true,
                    foo : "bar"
                },
                methods : {
                    main : function() {
                        console.log(self.properties.foo); // console logs "bar"
                    }
                }
            };

            this.init = function(options) {
                self = $.extend({}, defaults, options); // set properties to defaults unless options were provided
                self.methods.main();
            };

            this.init(options);

            return this;
        }

    });

})( jQuery, window, document );

$(window).load(function() {
    $.MyObject({
        properties : {
            foo : "baz"
        },
        methods : {
            main : function() {
                if(self.properties.prop) { // Uncaught TypeError: Cannot read property 'prop' of undefined
                    console.log(self.properties.foo); // Uncaught TypeError: Cannot read property 'foo' of undefined
                }
            }
        }
    });
});

我可能会大大过度复杂我想要做的事情。在这一点上,我认为可能有更好的方法来做到这一点。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可能希望在init()中进行深度扩展。您也可以通过main()上的call()将当前选项作为“this”传递。

;(function ( $, window, document, undefined ) {
  $.extend({
    MyObject : function(options) {

      // ---------------
      // enforce singleton pattern
      // ---------------
      $.MyObject = function() {
        if (typeof $.MyObject === 'undefined') { return this; }
        console.log('$.MyObject is a singleton...');
        return $.MyObject;
      };
      // ---------------

      // ---------------
      // establish default options
      // ---------------
      var self = {};
      var defaults = {
        properties : {
          prop : true,
          foo : "bar"
        },
        methods : {
          main : function() { console.log( this.properties.foo ); }
        }
      };
      // ---------------

      // ---------------
      // Override default options and execute main() in the context
      // of our current options
      // ---------------
      this.init = function(options) {
        self = $.extend(true, {}, defaults, options);
        self.methods.main.call(self);
      };
      this.init(options);
      // ---------------

      return this;
    }
  });
})( jQuery, window, document );

$(window).load(function() {
  var options = {
    properties : {
      bar : "foo"
    },
    methods : {
      main : function() {
        if(this.properties.prop) { console.log(this.properties.bar); }
      }
    }
  };

  $.MyObject(options);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>