jQuery插件范围问题

时间:2012-01-12 19:28:10

标签: javascript jquery-plugins scope

鉴于以下示例(如果您使用的是jsfiddle链接,请单击右侧的“内容”),为什么self在达到clickHelper()时会超出范围?

我可以想出两种方法来解决它...(1)我可以将其作为参数传递,或者(2)我可以在插件内部定义var self;function clickHelper()以上)。

我不想做#1,因为在我的实际实现中,我已经有一堆参数和一堆辅助函数......我希望使用范围来避免传递self到处都是。

我不想使用#2,因为看起来如果这个插件用于页面上的多个元素,可能会有竞争条件......我的假设是jQuery有1个插件实例,并且因此var self只会存在一次。

我基本上都在寻找将this保留在为jQuery插件引发的click事件范围内的最佳实践。

http://jsfiddle.net/QZc9v/

<div id="a1">
    content
</div>

<script type="text/javascript">=
    function info(n, s) {
        var id = (typeof (s.id) == "undefined") ? '' : ': ' + s.id;
        alert(n + ': ' + s + ': ' + typeof (s) + id);
    }

    (function ($) {    
        $.fn.myPlugin = function () {
        function clickHelper() {
            info('self in the Helper...', self);
            self.innerHTML += '2';
        }
        function clickHandler() {
            var self = this;
            info('self in the Handler', self);
            self.innerHTML += '1';
            clickHelper();
        }
        this.bind('click', clickHandler);
        };
    }(jQuery));

    $(function () {
        $('#a1').myPlugin();
    });
</script>

ETA:#1可能是最好的选择,如果你不介意额外的参数,因为#2会出现竞争条件/线程安全问题,如所示here(点击内容1 ,好的,然后内容2真的很快)。你可以通过在处理程序方法中定义你的帮助器方法来解决问题{2},这可能适用于你的所有帮助方法都支持你的处理程序方法。我想,#3,而不是像通常clickHelper()那样调用JavaScript函数,只需使用正确的闭包function(this) { var self = this; clickHelper() };

1 个答案:

答案 0 :(得分:1)

<强> Guide on closures and scoping

变量仅适用于创建它们的函数。因此,通过在self内创建clickHelper,您只能将其作为clickHelpers函数的局部变量。

将其移动到myPlugins范围内,现在可以访问嵌套函数。

<强> Live Demo

 $.fn.myPlugin = function () {
        var self = {}; // self declared here instead can be used within this scope now
        function clickHelper() {
            info('self in the Helper...', self);
            self.innerHTML += '2';
        }
        function clickHandler() {
            self = this;
            info('self in the Handler', self);
            self.innerHTML += '1';
            clickHelper();
        }
        this.bind('click', clickHandler);
    };