jQuery Boilerplate - 失去访问"这个"范围

时间:2014-12-01 14:18:25

标签: javascript jquery jquery-boilerplate

我正在尝试使用jQuery Boilerplate编写我的第一个插件。我遇到的问题是,一旦我尝试处理一个事件,我就会失去对this范围的访问权限,我认为应该variable shadowing。这似乎是jQuery Boilerplate的一个常见用例,所以我猜我错了。

我在SO上发现了两个类似的问题:

  1. jQuery plugin object: attached an event handler via .on() and now have a scope issue of this. (the main plugin object) - 没有答案
  2. Javascript scoping Issue using JQuery Boilerplate - 不回答我的问题
  3. 我已经创建了一个最小的样本来证明这个问题。

    HTML

    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
    </ul>
    

    PLUGIN

    (function($, window, document, undefined) {
        'use strict';
    
        var pluginName = 'elementValueLog',
                defaults = {};
    
        function Plugin(element, options) {
            this.element = element;
            this.$element = $(element);
            this.settings = $.extend({}, defaults, options);
            this._defaults = defaults;
            this._name = pluginName;
    
            this.init();
        }
    
        $.extend(Plugin.prototype, {
            init: function() {
                this.$element.on('click', this.doLog);
            },
            doLog: function() {
                // HERE: I can't figure out how to access the Plugin "this" scope
                // I want to be able to use "element", "$element", "settings", etc.
                console.log(this.$element.val().trim());
            }
        });
    
        $.fn[pluginName] = function(options) {
            this.each(function() {
                if (!$.data(this, "plugin_" + pluginName)) {
                    $.data(this, "plugin_" + pluginName, new Plugin(this, options));
                }
            });
            return this;
        };
    }(jQuery, window, document, undefined));
    

    使用插件

    $(document).ready(function() {
        $('li').elementValueLog();
    });
    

    我希望将此作为答案添加,但被标记为“重复”会阻止这种情况。在尝试了另一篇文章的答案中显示的几种方法之后,我找到了一个解决方案。我个人认为我的问题具体到足以独立存在,因为另一篇文章中的“规范”答案相当广泛。

    对于browsers that support bindinit功能可以像这样更改:

    init: function() {
        this.$element.on('click', this.doLog.bind(this));
    },
    

    因为我需要支持IE 8,所以我将使用jQuery.proxy

    init: function() {
        this.$element.on('click', $.proxy(this.doLog, this));
    },
    

    doLog功能可以引用this.elementthis.$elementthis.settings等。

    基于Jeff Watkins的回答:

    init: function() {
        var plugin = this;
        var doLog = function() {
            console.log(plugin.$element.val().trim());
        };
        this.$element.on('click', doLog);
    },
    

    此解决方案的好处是可以保留this上下文,同时可以访问插件的this上下文。

1 个答案:

答案 0 :(得分:1)

&#34;这&#34;是你在堆栈中的位置的上下文,所以&#34;这&#34;在一个事件中实际上是事件,如果这是有道理的。这是一个常见的编程概念。

我经常使用&#34;这个&#34;的高速缓存版本。 (如打电话)如果你需要打电话就可以使用。

$.fn[pluginName] = function(options) {
    var caller = this;
    this.each(function() {
        if (!$.data(caller, "plugin_" + pluginName)) {