Function オブジェクトの読み取り専用プロパティ name は、作成時に付けられた名前、もしくは無名関数の場合は anonymous を返します。
このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力していただける場合は、 https://github.com/mdn/interactive-examples をクローンしてプルリクエストを送信してください。
Function.name のプロパティ属性 |
|
|---|---|
| 書込可能 | 不可 |
| 列挙可能 | 不可 |
| 設定可能 | 可 |
configurable 属性も false であることに注意してください。例
関数文の名前
name プロパティは関数文の名前を返します。
function doSomething() {}
doSomething.name; // "doSomething"
関数コンストラクターの名前
構文 new Function(...) または単に Function(...) で関数を作成すると、 Function オブジェクトが作成され、その名前は "anonymous" になります。
(new Function).name; // "anonymous"
Inferred function names
変数とメソッドは、構文上の位置から無名関数の名前を推論できます (ECMAScript 2015 から)。
let f = function() {};
let object = {
someMethod: function() {}
};
console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"
関数式 で、name を持つ関数を定義することができます:
let object = {
someMethod: function object_someMethod() {}
};
console.log(object.someMethod.name); // "object_someMethod" と表示
try { object_someMethod } catch(e) { console.log(e); }
// ReferenceError: object_someMethod is not defined
The name property is read-only and cannot be changed by the assigner operator:
Example below contradicts with what is said at the beginning of this section and doesn't work as described.
let object = {
// anonymous
someMethod: function() {}
};
object.someMethod.name = 'otherMethod';
console.log(object.someMethod.name); // someMethod
name を変更したければ、Object.defineProperty() を使ってください。
短縮メソッドの名前
var o = {
foo(){}
};
o.foo.name; // "foo";
バインドされた関数の名前
Function.bind() が関数を作成する時、その名前は "bound " とその関数名を合わせたものとなります。
function foo() {};
foo.bind({}).name; // "bound foo"
ゲッターとセッターの関数名
get と set を使う時は、 "get" や "set" が関数名に含まれます。
let o = {
get foo(){},
set foo(x){}
};
var descriptor = Object.getOwnPropertyDescriptor(o, "foo");
descriptor.get.name; // "get foo"
descriptor.set.name; // "set foo";
クラスでの関数名
obj.constructor.name でオブジェクトの「クラス」を知ることができます (ただし、下記の警告を確認してください)。
function Foo() {} // ES2015 構文の場合: class Foo {}
var fooInstance = new Foo();
console.log(fooInstance.constructor.name); // "Foo" と表示
警告: スクリプトインタープリターは、関数が自身の name プロパティを持っていない場合に限り、組み込みの Function.name プロパティを設定します (9.11.2. of the ECMAScript2015 Language Specification セクションをご覧ください)。しかし ES2015 では、static キーワードを指定すると、その静的メソッドはクラスのコンストラクタ関数の OwnProperty として設定されます (ECMAScript2015, 14.5.14.21.b + 12.2.6.9)。
従って、name() という静的メソッドを持つクラスでは、事実上そのクラス名を取得することはできません:
class Foo {
constructor() {}
static name() {}
}
static name() メソッドが存在する場合、Foo.name はクラス名ではなく、 name() 関数オブジェクトへの参照を持つことになります。Chrome や Firefox では、上記の ES2015 の構文によるクラス定義は、下記の ES5 構文のコードと同じような挙動をします:
function Foo() {}
Object.defineProperty(Foo, 'name', { writable: true });
Foo.name = function() {};
fooInstance.constructor.name で fooInstance のクラスを取得しようとしても、得られるのはクラス名ではなく静的メソッドへの参照です。例えば:
let fooInstance = new Foo(); console.log(fooInstance.constructor.name); // 関数 name() を表示
先ほどの ES5 の構文の例では、Chrome や Firefox での Foo.name の静的な定義の際に writable を指定しています。このような独自の手法を用いなければ、デフォルトでは read-only となります:
Foo.name = 'Hello'; console.log(Foo.name); // Foo が static name() を持つ場合は "Hello"、そうでなければ "Foo" と表示する。
従って、Function.name プロパティが常にクラス名を保持しているとは考えないほうがいいでしょう。
関数名としての Symbol
Symbol を関数名として使用し、Symbol が description を持っている場合、関数名はブラケット [ ] 内の description となります。
let sym1 = Symbol("foo");
let sym2 = Symbol();
let o = {
[sym1]: function(){},
[sym2]: function(){}
};
o[sym1].name; // "[foo]"
o[sym2].name; // ""
JavaScript の圧縮とミニファイ
警告: Function.name を使用しているときに、JavaScript の圧縮(ミニファイ)や難読化のような変換を行う際には注意が必要です。これらのツールはJavaScript ビルドパイプラインの一部として、本番環境に設置する前にプログラムのサイズを縮小するためによく使用されます。それらの変換は、ビルド時に関数名を変更することがあります。
次のようなソースコードは、
function Foo() {};
let foo = new Foo();
if (foo.constructor.name === 'Foo') {
console.log("'foo' は 'Foo' のインスタンスである");
} else {
console.log('おおっと!');
}
このように圧縮されるかもしれません。
function a() {};
let b = new a();
if (b.constructor.name === 'Foo') {
console.log("'foo' は 'Foo' のインスタンスである");
} else {
console.log('おおっと!');
}
非圧縮版では、プログラムは真の方の分岐を実行し、「'foo' は 'Foo' のインスタンスである」と表示するのに対し、圧縮版は異なる振る舞いをし、偽の方の分岐を実行します。それゆえ、上述の例のように Function.name に依存するならば、ビルドパイプラインが関数名を変更しないようにするか、特定の関数名を想定しない構造にする必要があります。
仕様書
| 仕様書 | 状態 | 備考 |
|---|---|---|
| ECMAScript 2015 (6th Edition, ECMA-262) name の定義 |
標準 | 初回定義 |
| ECMAScript (ECMA-262) name の定義 |
現行の標準 |
ブラウザーの互換性
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
name | Chrome 完全対応 15 | Edge 完全対応 14 | Firefox 完全対応 1 | IE 未対応 なし | Opera 完全対応 10.5 | Safari 完全対応 6 | WebView Android 完全対応 1 | Chrome Android 完全対応 18 | Firefox Android 完全対応 4 | Opera Android 完全対応 11 | Safari iOS 完全対応 6 | Samsung Internet Android 完全対応 1.0 | nodejs 完全対応 あり |
| Configurable: true | Chrome 完全対応 43 | Edge 完全対応 14 | Firefox 完全対応 38 | IE 未対応 なし | Opera 完全対応 30 | Safari 未対応 なし | WebView Android 完全対応 43 | Chrome Android 完全対応 43 | Firefox Android 完全対応 38 | Opera Android 完全対応 30 | Safari iOS 未対応 なし | Samsung Internet Android 完全対応 4.0 | nodejs ? |
| Inferred names on anonymous functions | Chrome 完全対応 51 | Edge
部分対応
14
| Firefox 完全対応 53 | IE 未対応 なし | Opera 完全対応 38 | Safari 完全対応 10 | WebView Android 完全対応 51 | Chrome Android 完全対応 51 | Firefox Android 完全対応 53 | Opera Android 完全対応 41 | Safari iOS 完全対応 10 | Samsung Internet Android 完全対応 5.0 | nodejs ? |
凡例
- 完全対応
- 完全対応
- 部分対応
- 部分対応
- 未対応
- 未対応
- 実装状況不明
- 実装状況不明
- 実装ノートを参照してください。
- 実装ノートを参照してください。