内部事件函数中的Javascript上下文

时间:2013-01-16 08:23:27

标签: javascript javascript-events

我试图在elem的onclick中访问MainObj的属性。 有没有更好的方法来设计它所以参考不会是“MainObj.config.url” 但是像这样的东西.config.url

示例代码:

var MainObj = {
      config: { url: 'http://www.mysite.com/'},
      func: function()
      {
          elem.onclick = function() {
           var url_pre = MainObj.config.url+this.getAttribute('href');

           window.open(url_pre, '_new');
          };
      }

}

3 个答案:

答案 0 :(得分:4)

对象内的

'this'总是引用它自己(对象)。只需将上下文保存到变量中即可使用它。变量通常被称为'_this','self'或'_self'(这里我用_self):

var MainObj = {
  config: { url: 'http://www.mysite.com/'},
  func: function()
  {
      var _self = this;
       elem.onclick = function() {
       var url_pre = _self.config.url+this.getAttribute('href');

       window.open(url_pre, '_new');
      };
  }
}

答案 1 :(得分:3)

您可以使用Module pattern

var MainObj = (function () {
      var config = { url: 'http://www.mysite.com/'};
      return {
         func: function() {
             elem.onclick = function() {
                 var url_pre = config.url+this.getAttribute('href');
                 window.open(url_pre, '_new');
             };
          }
      };
}());

首先,我们在本地函数范围中定义config对象。之后,我们在return语句中返回一个对象文字。该对象包含func函数,稍后可以调用它:MainObj.func

答案 2 :(得分:1)

肯定有更好的方法......但我必须说:在方法中绑定一个事件处理程序是 - 我很抱歉这是一个可怕的想法。
您可能需要检查MDN,了解有关this关键字的内容,因为this混淆并绊倒了许多人。例如,在您的代码段中,正确使用了this:它将引用elem。话虽如此,这是你可能做的事情:

var MainObj = (function()
{
    var that = {config: { url: 'http://www.google.com/'}};//create closure var, which can be referenced whenever you need it
    that.func = function()
    {
        elem.onclick = function(e)
        {
            e = e || window.event;
            window.open(that.config.url + this.getAttribute('href'));
        };
    };
    return that;//expose
}());

但正如我所说,在方法中绑定一个事件处理程序根本就没有办法:

MainObj.func();
MainObj.func();//shouldn't be possible, but it is

为什么不,只需这样做:

var MainObj = (function()
{
    var that = {config: { url: 'http://www.google.com/'}};
    that.handler = function(e)
    {
        e = e || window.event;
        window.open(that.config.url + this.getAttribute('href'));
    };
    that.init = function(elem)
    {//pass elem as argument
        elem.onclick = that.handler;
        delete that.init;//don't init twice
        delete that.handler;//doesn't delete the function, but the reference too it
    };
    return that;//expose
}());
MainObj.init(document.body);

即便如此,这不是我在所有中编写此代码的方式,但是我确实偶尔会使事情过于复杂。但是要研究如何在JS中确定调用上下文,以及闭包,对象引用和GC如何工作......这是值得的。

更新
根据OP的要求 - 另一种方法

(function()
{
    'use strict';
    var config = {url: 'http://www.google.com/'},
    handlers = {load: function(e)
        {
           document.getElementById('container').addEventListener('click',handlers.click,false);
        },
        click: function(e)
        {
            e = e || window.event;
            var target = e.target || e.srcElement;
            //which element has been clicked?
            if (target.tagName.toLowerCase() === 'a')
            {
                window.open(config.url + target.getAttribute('href'));
                if (e.preventDefault)
                {
                    e.preventDefault();
                    e.stopPropagation();
                }
                e.returnValue = false;
                e.cancelBubble = true;
                return false;//overkill
            }
            switch(target.id)
            {
                case 'foo':
                    //handle click for #foo element
                return;
                case 'bar': //handle bar
                return;
                default:
                   if (target.className.indexOf('clickClass') === -1)
                   {
                       return;
                   }
            }
            //treat elements with class clickClass here
        }
    };
    document.addEventListener('load',handlers.load,false);//<-- ~= init
}());

这只是一个例子,它还远未完成。像preventDefault调用之类的东西,我倾向于避免(为了X浏览器的兼容性和易用性,我增加了Event.prototype)。
我不会发布大量链接到我自己的问题,但看看我的个人资料,并检查JavaScript问题。您可能会对以下几个示例感兴趣(包括如何在X浏览器上下文中扩充Event.prototype)