正确获取 "this" in jQuery 插件成员

Properly get "this" in jQuery plugin member

我有一个 JavaScript 模块,我想为其创建一个 jQuery 插件接口。 模块本身是这样的:

var Foo  = (function () {
    "use strict";
    var self = {};


    self.add = function (selector, otherParam) 
    {

        // Does things unto selector.
        // Precisely what it does doesn't matter.
    };
    return self;
}());

并被使用,成功,像这样:

Foo.add(a);

现在,我想创建一个与该模块接口的插件, 所以我可以像这样使用它:

$.fn.foo = Foo;
$.fn.foo.add = function (param) {
    var selector = this;
    Foo.add(selector, param);
}
$(elem).foo.add(a);

我面临的问题是我无法 "this" 在 .add() 中工作。 我设法做到这一点的最好方法是不要让 Foo 进行自我初始化, 并使用如下语法:

$.fn.foo = Foo;
$(elem).foo().add(a);

它有效,但我发现它在美学上不那么令人愉悦,也不那么 "clean"。

有办法吗?我是不是完全走错了路?

感谢您的任何意见,如果此问题已得到答复或以任何其他方式不合适,我提前致歉。 我确实搜索了答案,但我并不精通插件创作,也不是 jQuery 本身的专家。

TL;DR: 我有一个像上面 Foo 这样的模块,我想像 jQuery 插件一样访问它的成员。

这是我通常使用的模式的简化版本(删除了错误检查和额外功能)。

它使用一个 class 函数和一个 插件桥 扩展方法来允许附加到多个元素。使用字符串选项值调用方法:

var Foo = (function () {
    "use strict";

    // Constructor
    function Foo($element, options){
        this.$element = $element;
        this.options = options
        this.fooVal = 0;
    }

    // Create method (called from bridge)
    Foo.prototype.onCreate = function(){
        this.fooVal = ~~this.$element.text()
    };

    // Add the specified val to the elements current value    
    Foo.prototype.add = function (val) {
        this.fooVal += val;
        // Update the element text with the new value
        this.$element.text(this.fooVal);
    };
    return Foo;
})();

// Create a bridge to each element that needs a Foo
$.fn.foo = function (options, args) {
    this.each(function () {
        var $element = $(this);
        // Try to get existing foo instance
        var foo = $element.data("Foo");
        // If the argument is a string, assume we call that function by name
        if (typeof options == "string") {
            foo[options](args);
        }
        else if (!foo) {
            // No instance. Create a new Foo and store the instance on the element
            foo = new Foo($element, options);
            $element.data("Foo", foo);
            // Record the connected element on the Foo instance
            foo.$element = $element;
            // Call the initial create method
            foo.onCreate();
        }
    });
}

// testing
console.clear();
$('#test').foo();
$('#button2').click(function () {
    $('#test').foo("add", 2);
});

$('#button10').click(function () {
    $('#test').foo("add", 10);
});

对于您的示例,Foo 从元素文本中获取初始值,随后的 "add" 调用会修改该值。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/

备注:

  • ~~ 只是 parseInt()
  • 的快捷方式
  • 您可以通过选项参数提供初始值(在第一个示例中被忽略)。请参阅以下内容:

例如

// Create method (called from bridge)
Foo.prototype.onCreate = function(){
    this.fooVal = this.options.value || ~~this.$element.text()
    // Set initial value
    this.$element.text(this.fooVal);
};

并从

开始
$('#test').foo({value: 999});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/4/