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

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

本文关键字:范围 问题 方法 覆盖 jQuery 对象 文字 扩展      更新时间:2023-09-26

我编写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
                }
            }
        }
    });
});

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

有什么想法吗?

你可能想要在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>