【问题标题】:call to function inside jQuery-ui plugin has wrong context?jQuery-ui 插件内的函数调用有错误的上下文?
【发布时间】:2012-05-15 04:04:46
【问题描述】:

我有一个 jQuery UI 函数,在 _create 函数中我有 var self = this,所以我可以从插件中的其他函数访问插件上下文。

我在 _create 函数中也有这段代码:

//setup sortable handler
if (self.options.sortable !== false) {

     var soptions = {
         items:'.tagit-choice',
         containment:'parent',
         start:function (event, ui) {
             console.log('sorting started', event, ui);
             self._sortable.tag = $(ui.item);
             self._sortable.origIndex = self._sortable.tag.index();
         },
         update:function (event, ui) {
             console.log('sorting started', event, ui);
             self._sortable.newIndex = self._sortable.tag.index();
             self._moveTag(self._sortable.origIndex, self._sortable.newIndex);
             console.log('moved tag', self._sortable.origIndex, 'to', self._sortable.newIndex);

         }
     };

     if (self.options.sortable == 'handle') {
         $('.tagit-choice', this.element).prepend('<a class="ui-icon ui-icon-grip-dotted-vertical" style="float:left"></a>');
         soptions.handle = 'a.ui-icon';
         soptions.cursor = 'move';
     }

     self.element.sortable(soptions);
 }

在插件内设置可排序。

它调用了self._moveTag,其中我调用了console.log(self),我希望self 是插件实例,但实际上它是DOMWindow。这是为什么呢?

_moveTag: function (old_index, new_index) {
    console.log(self);
    self.tagsArray.splice(new_index, 0, self.tagsArray.splice(old_index, 1)[0]);
    for (var ind in self.tagsArray)
        self.tagsArray[ind].index = ind;

    if(self.options.select){
        $('option:eq(' + old_index + ')', this.select).insertBefore($('option:eq(' + new_index + ')', this.select));
    }
},


希望这个例子更清楚:
(function($) {

    $.widget("ui.widgetName", {

        options: {
            sortable: true
        },

        _sortable: {},

        _create: function() {

            var self = this;

            if (self.options.sortable !== false) {
                self.element.sortable({
                    items: '.tagit-choice',
                    containment: 'parent',
                    start: function(event, ui) {
                        self._sortable.tag = $(ui.item);
                        self._sortable.origIndex = self._sortable.tag.index();
                    },
                    update: function(event, ui) {
                        self._sortable.newIndex = self._sortable.tag.index();
                        self._moveTag(self._sortable.origIndex, self._sortable.newIndex);
                    }
                });
            }
        },

        _moveTag: function(old_index, new_index) {
            console.log(self); // <-- this returns DOMWindow?!?!?
        }
    });
})(jQuery);​

【问题讨论】:

  • 你能把它缩小到一个完整的小例子吗?除非我们能在上下文中看到自赋值,否则很难分辨出哪里出了问题。
  • 我添加了一个希望更清晰的示例?

标签: javascript jquery jquery-ui scope closures


【解决方案1】:

您为什么希望 self 完全在 _moveTag 中定义?显然有人将self 泄漏到window.self 中,而您在_moveTag 中发现了不好的self,而self 恰好是window;给定这样的东西:

(function($) {
    $.widget('ui.pancakes', {
        _create: function() {
            var self = this;
            self._moveTag();
        },
        _moveTag: function() {
            // ...
        }
    });
})(jQuery);

_create 中的self 是您希望您的self 成为的小部件,但self 不在_moveTag 的范围内,_moveTag 正在从其他地方获取泄露的window.self .所以你可以在_create 中使用self 以及在_create 中定义的任何函数,你会得到期望的结果;但是_moveTag 以通常的方式定义为小部件方法(而不是在_create 的范围内),因此它会拾取坏的外部self 并且selfwindow

我认为你的私人_moveTags 方法犯了self 滥用。您应该在小部件方法中使用this,并确保调用者使用正确的上下文; jQuery-UI 将为您调用具有正确上下文的公共方法,您应该能够非常轻松地自己处理私有方法(例如_moveTag)。

这里有一个快速演示用于说明:http://jsfiddle.net/ambiguous/UhE3F/


一个小小的调查揭示了一个令人震惊的事实:window 应该有一个self property

window.self

返回对窗口对象的对象引用。

事实证明,var self = this 约定是有史以来最糟糕的想法之一,或者至少使用名称 self 因为这是一个糟糕的想法。这是多么令人困惑的错误来源。

【讨论】:

  • 没有人泄露window.selfwindow 对象总是公开一个评估为自身的self 属性。
  • @FrédéricHamidi:是的,我刚刚意识到,我自己从来没有真正使用过它,现在我必须改变我自己糟糕的var self 习惯以避免像这样令人讨厌的错误。知道这个糟糕的var self 约定是谁的错吗?我认为一个好的老式女巫燃烧是秩序:)
  • 是的,使用self 作为this 的别名应该小心,忘记将其声明为本地对象,你最终会弄乱window 对象,这不是好东西……
  • 啊,你是对的,我不知道为什么我在那里使用self而不是this...无论如何,给你一个绿色的勾!
  • @FrédéricHamidi:在使用var self 玩弄手榴弹多年后,现在我必须重新编程我的手指以说出var _thisvar that。哦,哦,好吧,总有一瓶不错的红葡萄酒可以帮上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
  • 2013-05-16
  • 2021-10-10
  • 2018-11-09
  • 2016-04-07
相关资源
最近更新 更多