非標準
この機能は標準ではなく、標準化の予定もありません。公開されているウェブサイトには使用しないでください。ユーザーによっては使用できないことがあります。実装ごとに大きな差があることもあり、将来は振る舞いが変わるかもしれません。

Gecko 43 で廃止 (Firefox 43 / Thunderbird 43 / SeaMonkey 2.40)
この機能は廃止されました。まだいくつかのブラウザーで動作するかもしれませんが、いつ削除されてもおかしくないので、使わないようにしましょう。

__noSuchMethod__ プロパティは、オブジェクトで存在しないメソッドが呼び出されたときに実行される関数を参照するために使用されていましたが、この機能は利用できなくなりました。

__noSuchMethod__ は廃止されしたが、 ECMAScript 2015 (ES6) 仕様には Proxy オブジェクトがあり、以下のようなことを (それ以上のことも) 実現できます。

構文

obj.__noSuchMethod__ = fun

引数

fun
以下の引数をとる関数
function (id, args) { . . . }
id
呼び出された未定義のメソッドの名前
args
そのメソッドへ渡された引数の配列

解説

オブジェクトで定義されていない関数の呼び出しを試みても、標準の挙動では TypeError 例外が投げられるだけです。オブジェクトのメンバー関数として __noSuchMethod__ を定義しておく事でこの挙動を回避できます。 __noSuchMethod__ として定義される関数は 2 つの引数をとります。 1 つ目の引数は呼び出しが試みられたメソッドの名前を表し、 2 つ目の引数はそのメソッドへ渡された引数の配列を表します。この 2 つ目の引数は実配列です。配列を模したオブジェクトである arguments オブジェクトではありません。

このメソッドが呼び出せない場合、つまり既定値の undefined であるか削除されていた場合、または関数以外が手動で設定されていた場合は、JavaScript エンジンは TypeError を投げる動作に戻ります。

__noSuchMethod__ の基本的な使い方

var o = {
  __noSuchMethod__: function(id, args) { 
                      console.log(id, '(' + args.join(', ') + ')'); 
                    }
};

o.foo(1, 2, 3);
o.bar(4, 5);
o.baz();

// 出力
// foo (1, 2, 3)
// bar (4, 5)
// baz ()

__noSuchMethod__ を使用して多重継承をシミュレートする

多重継承の基本形を実装するコードの例を以下に示します。

// Doesn't work with multiple inheritance objects as parents
function noMethod(name, args) {
  var parents = this.__parents_;

  // Go through all parents
  for (var i = 0; i < parents.length; i++) {
    // If we find a function on the parent, we call it
    if (typeof parents[i][name] == 'function') {
      return parents[i][name].apply(this, args);
    }
  }

  // If we get here, the method hasn't been found
  throw new TypeError;
}

// Used to add a parent for multiple inheritance
function addParent(obj, parent) {
  // If the object isn't initialized, initialize it
  if (!obj.__parents_) {
    obj.__parents_ = [];
    obj.__noSuchMethod__ = noMethod;
  }

  // Add the parent
  obj.__parents_.push(parent);
}

使用例を以下に示します。

// Example base class 1
function NamedThing(name) {
  this.name = name;
}

NamedThing.prototype = {
  getName: function() { return this.name; },
  setName: function(newName) { this.name = newName; }
}

// Example base class 2
function AgedThing(age) {
  this.age = age;
}

AgedThing.prototype = {
  getAge: function() { return this.age; },
  setAge: function(age) { this.age = age; }
}

// Child class. inherits from NamedThing and AgedThing
// as well as defining address
function Person(name, age, address){
  addParent(this, NamedThing.prototype);
  NamedThing.call(this, name);
  addParent(this, AgedThing.prototype);
  AgedThing.call(this, age);
  this.address = address;
}

Person.prototype = {
  getAddr: function() { return this.address; },
  setAddr: function(addr) { this.address = addr; }
}

var bob = new Person('bob', 25, 'New York');

console.log('getAge is ' + (('getAge' in bob) ? 'in' : 'not in') + ' bob');
// getAge is not in bob

console.log("bob's age is: " + bob.getAge());
// bob's age is: 25

console.log('getName is ' + (('getName' in bob) ? 'in' : 'not in') + ' bob');
// getName is not in bob

console.log("bob's name is: " + bob.getName());
// bob's name is: bob

console.log('getAddr is ' + (('getAddr' in bob) ? 'in' : 'not in') + ' bob');
// getAddr is in bob

console.log("bob's address is: " + bob.getAddr());
// bob's address is: New York

仕様書

どの仕様にも含まれていません。この機能は削除されました。 バグ 683218 をご覧ください。

ブラウザーの対応

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
基本対応
非推奨非標準
Chrome 未対応 なしEdge 未対応 なしFirefox 未対応 1 — 43IE 未対応 なしOpera 未対応 なしSafari 未対応 なしWebView Android 未対応 なしChrome Android 未対応 なしEdge Mobile 未対応 なしFirefox Android 未対応 4 — 43Opera Android 未対応 なしSafari iOS 未対応 なしSamsung Internet Android 未対応 なしnodejs 未対応 なし

凡例

未対応  
未対応
非標準。ブラウザー間の互換性が低い可能性があります。
非標準。ブラウザー間の互換性が低い可能性があります。
非推奨。新しいウェブサイトでは使用しないでください。
非推奨。新しいウェブサイトでは使用しないでください。

ドキュメントのタグと貢献者

このページの貢献者: mfuji09, teoli, yyss, ethertank, saneyuki_s, Potappo, Mgjbot, Plum.the.goodman
最終更新者: mfuji09,