JavaScriptでnewを忘れるとグローバル変数を上書きしてしまう

スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 |
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般

JavaScriptでnewを忘れるとグローバル変数を上書きしちゃうので、ちょっと危険だという記事を読みました。

スポンサーリンク

JavaScriptのnew – watawata日記

function User(first, last){
    this.name = first + " " + last;
}
var user = new User("John", "Resig");
user.name // "John Resig" 

しかしこの方法だとnewを忘れた場合に問題があります。thisにグローバルオブジェクトがセットされるためグローバル変数を上書きしてしまいます。

興味深かったとともに、jqueryでのmakeClass()の実装が、よく抜け道突いてるなぁ、と感心しました。
jqueryのmakeClass()は、newなしで呼ばれると、実際には2回呼ばれることになるそうなのですが、分かりやすく実感するために、以下のようにコードを書き加えてみました。

function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      document.write("if true:<br>" + this + "<br>" + arguments.callee.caller + "<br>");
      if ( typeof this.init == "function" )
        this.init.apply( this, args.callee ? args : arguments );
    } else {
      document.write("else:<br>" + this + "<br>" + arguments.callee.caller + "<br>");
      return new arguments.callee( arguments );
    }
  };
}
 
var User = makeClass();
User.prototype.init = function(first, last){
  this.name = first + " " + last;
};
var user = User("John", "Resig");
user.name // => "John Resig"

これで実行したところ・・・

else:
[object Window]
null
if true:
[object Object]
function (args) { if (this instanceof arguments.callee) { document.write("if true:
" + this + "
" + arguments.callee.caller + "
"); if (typeof this.init == "function") { this.init.apply(this, args.callee ? args : arguments); } } else { document.write("else:
" + this + "
" + arguments.callee.caller + "
"); return new (arguments.callee)(arguments); } }

と出力され、まず1回目にelse節が呼ばれた後、if文がtrueと評価されて呼び出されていることを確認できる。
また、this と arguments.callee.caller も、1回目と2回目で違うことを確認できる。

スポンサーリンク
 
スポンサーリンク