JavaScript の new 演算子の意味2005年10月24日 16時25分

JavaScript における new 演算子の動作は大まかにいって以下のとおりである。(new F() とした場合。)

  1. 新しいオブジェクトを作る。
  2. 1 で作ったオブジェクトの [[Prototype]] 内部プロパティ (__proto__ プロパティ) に F.prototype の値を設定する。
    • F.prototype の値がオブジェクトでないのなら代わりに Object.prototype の値を設定する。
  3. F を呼び出す。このとき this の値は 1 で作ったオブジェクトとし、引数には new 演算子とともに使われた引数をそのまま用いる。
  4. 3 の返り値がオブジェクトならそれを返す。そうでなければ 1 で作ったオブジェクトを返す。

ここで「オブジェクトである」というのはプリミティブ値 (文字列、数値、真偽値、undefinednull) ではないということだ。new String("string")new Number(123)new Boolean(true) はオブジェクトだが "string"123true はオブジェクトではない。

コードであらわすと以下のようになる。

Function.prototype.construct = function () {
  var newInstance = new Object();
  if (this.prototype instanceof Object)
    newInstance.__proto__ = this.prototype;

  var returnValue = this.apply(newInstance, arguments);
  if (returnValue instanceof Object)
    return returnValue;
  return newInstance;
};

var o = F.construct(arg); // == new F(arg)

new F() としたとき、実際に F が呼び出される前に新たなオブジェクトが作られるが、そのオブジェクトの生成にあたっては F.prototype の値が参考にされるのみで F 自体は直接関わってはいない。だからこそ一時的なコンストラクタを使って継承を実現ということもできる。

そして、それと同様に考えれば、「prototype.js を用いた OOP で、後方参照できるクラスを宣言する」(Noncommutative Field) で触れられていた配列として渡された引数を用いて new するということは以下のように実現できる。

Function.prototype.applyNew = function (args) {
  var Constructor = function () {};
  Constructor.prototype = this.prototype;
  var instance = new Constructor();
  var result = this.apply(instance, args);
  return (result instanceof Object) ? result : instance;
};

var o = F.applyNew([param1, param2]); // == new F(param1, param2)

余談になるが、F の返り値がオブジェクトでないとき、new F() の値には F の返り値ではなく新たに作られたオブジェクトが使用されるというのは改めて仕様書を読むまで気づかなかった。これまで以下のように書いていたのはまったくの見当違いだったのか。(というかろくにテストしていないのがばればれ。)

function F(arg)
{
  if (!arg) return null;

  ...
}

var o = new F(someArg);

参考

コメント

_ Word ― 2005年10月25日 09時18分

Well done

_ ほげほげ ― 2011年07月07日 13時59分

なるほど!! ですね。 参考になりました。

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※投稿には管理者が設定した質問に答える必要があります。

名前:
メールアドレス:
URL:
次の質問に答えてください:
「ハイパーテキストマークアップ言語」をアルファベット4文字でいうと?

コメント:

トラックバック

このエントリのトラックバックURL: http://nanto.asablo.jp/blog/2005/10/24/118564/tb

_ あまきた日記 - 2006年09月20日 18時21分

new F() としたとき、実際に F が呼び出される前に新たなオブジェクトが作られるが、そのオブジェクトの生成にあたっては F.prototype の値が参考にされるのみで F 自体は直接関わってはいない。だからこそ一時的なコンストラクタを使って継承を実現ということもできる。 Ja

_ lesamoureusesの日記 - 2008年02月19日 17時56分

jquery.jsを読み解く:第1回 jQueryライブラリ(1?171行目)|gihyo.jp … 技術評論社を見ながら勉強。 0017: var jQuery = window.jQuery = function( selector, context ) { 0018: // The jQuery object is actually just the init constructor ’enhanced’ 0019: return