Extending/overriding jQuery 对象文字方法 - 超出范围的问题

Extending/overriding jQuery object literal methods - Out of scope issues

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

我正在编写的 jQuery 扩展中使用单例模式。这很好用,但是我希望能够 extend/override 我的单例对象的方法和属性。

为此,我有一个主 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
                }
            }
        }
    });
});

我可能把我想做的事情复杂化了。在这一点上,我认为可能有更好的方法来做到这一点。

有什么想法吗?

您可能想要深入扩展 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>