1

elem の onclick 内で MainObj のプロパティにアクセスしようとしています。参照が「MainObj.config.url」ではなく、this.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');
          };
      }

}
4

3 に答える 3

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');
      };
  }
}
于 2013-01-16T08:27:35.643 に答える
3

モジュールパターンを使用できます:

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

于 2013-01-16T08:27:28.083 に答える
1

確かにもっと良い方法があります...しかし、私が言わなければならないのは、メソッド内でイベントハンドラーをバインドすることは、-そしてこれについては申し訳ありません-ひどい考えです。多くの人を混乱させてつまずかせたので、キーワード
について何を言わなければならないかについて、MDN をチェックしたいかもしれません。たとえば、スニペットでは正しく使用されています。elem を参照します。そうは言っても、これはあなたができることです:thisthisthis

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 を拡張する方法に関する例を含む)。

于 2013-01-16T08:36:16.350 に答える