本頁の目次 目次

13 関数定義 (Function Definition)

Syntax
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
FormalParameterList :
Identifier
FormalParameterList , Identifier
FunctionBody :
SourceElements
Semantics

生成規則 FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody } は関数宣言のために次のように処理される:

  1. FormalParameterList で指定されるパラメータと FunctionBody で指定される body を用いて、セクション 13.2 に指定されるように 新しい Function オブジェクトを生成する。処理中の実行コンテキストのスコープ連鎖内を Scope として渡す。
  2. 名前 Identifier と Result(1) の値を用いて、(セクション10.1.3 で指定される) 現在の変数オブジェクト(variable object)のプロパティを生成する。

生成規則 FunctionExpression : function ( FormalParameterListopt ) { FunctionBody } は次のように評価される:

  1. FormalParameterList で指定されるパラメータと FunctionBody で指定される body を用いて、セクション 13.2 に指定されるように 新しい Function オブジェクトを生成する。処理中の実行コンテキストのスコープ連鎖内を Scope として渡す。
  2. Result(2) を返す。

生成規則 FunctionExpression : function Identifier ( FormalParameterListopt ) { FunctionBody } は次のように評価される:

  1. new Object() によるものであるかのように、新しいオブジェクトを生成する。
  2. スコープ連鎖の前に Result(1) を追加する。
  3. FormalParameterList で指定されるパラメータと FunctionBody で指定される body を用いて、セクション 13.2 に指定されるように 新しい Function オブジェクトを生成する。処理中の実行コンテキストのスコープ連鎖内を Scope として渡す。
  4. オブジェクト Result(1) 内にプロパティを生成する。プロパティ名は Identifier で、値は Result(3)、属性は { DontDelete, ReadOnly } である。
  5. スコープ連鎖の前から Result(1) を除去する。
  6. Result(3) を返す。

NOTE FunctionExpression 内の Identifier は、 FunctionExpressionFunctionBody の内部から参照が可能で、関数にそれ自身の再帰的呼び出しを許可する。しかしながら、 FunctionDeclaration とは異なり、 FunctionExpression 内の Identifier を参照はできず、 FunctionExpression を閉じるスコープに影響しない。

生成規則 FunctionBody : SourceElements は次のように評価される:

  1. 関数宣言のために SourceElements を処理する。
  2. SourceElements を評価する。
  3. Result(2) を返す。

13.1 定義 (Definitions)

関数オブジェクト生成の処理を述べるため、2 つの定義を要する:

13.1.1 等しい文法の生成規則 (Equated Grammar Productions)

FunctionBody 文法生成規則を用いる 2 者は、次のうちの一つが真であるとき、等しいものであると定義される:

  • 双方が、同じ ECMAScript プログラムのソーステキスト内の同じロケーションから取得された FunctionBody を用いている。このソーステキストはグローバルコードから構成され、セクション 10.1.2 の定義に従って、あるものはファンクションコードを含む。
  • 双方が、同じ eval 呼び出し(15.1.2.1) のソーステキスト内の同じロケーションから取得された FunctionBody を用いている。このソーステキストは eval コードから構成され、セクション 10.1.2 の定義に従って、あるものはファンクションコードを含む。

NOTE Function コンストラクタ呼び出し(15.3.1, 15.3.2) から取得される FunctionBody を用いる 2 者は、けして等しいとはみなされない。2 つの異なる eval 呼び出しから取得される FunctionBody を用いる 2 者も、それが同じ引数を渡されていたとしても、等しいとはみなされない。

13.1.2 結合オブジェクト (Joined Objects)

2 つ以上の Function オブジェクトが結合しているとき、それらは次の特殊な振る舞いを持つ:

  • オブジェクト O の非内部プロパティが作成または設定される時は、O に結合した全オブジェクトの該当するプロパティが常に直ちに作成され、同じ値および属性を設定される。
  • オブジェクト O の非内部プロパティが削除される時は、 O に結合した全オブジェクトの該当するプロパティも常に直ちに削除される。
  • オブジェクト OP が結合していれば、それらは互いに == および === として比較する。
  • 結合は過渡的で対称である。その結果、オブジェクト O および P が結合し、オブジェクト P および Q が結合する場合、オブジェクト O および Q も自動的に結合する。

NOTE 互いに結合した 2 つ以上のオブジェクトは、それらが異なる内部プロパティを持っているかもしれない点を除いて、事実上判別できない。本仕様において異なってもよいような内部プロパティこそが [[Scope]] である。結合されたオブジェクトは、正確な仕様技術用の道具としてこの標準の中で使用される。それは、実際の Function オブジェクトの実装法のガイドラインに使用されることを意図しない。もっと言えば、実際に実装は、2 つ以上の結合された Function オブジェクトの [[Scope]] プロパティの差が外部的に観測されず、その場合結合された Function オブジェクトの組を作らずに同じ Function オブジェクトを再使用するという時を検知するかもしれない。この標準は単に ECMAScript プログラムにみられる振る舞いの仕様であるので、これは合法的な最適化である。

13.2 Function オブジェクトの生成 (Creating Function Objects)

FormalParameterList で指定される選択的なパラメータのリスト、FunctionBody で指定される本文、Scope で指定されるスコープ連鎖を与えられ、Function オブジェクトは次のように生成される:

  1. このセクションのアルゴリズムのこれまでの呼び出しで生成されるオブジェクト E がすでに存在している場合、そしてその、このセクションのアルゴリズムの呼び出しが、今回与えられた FunctionBody と等しい FunctionBody を与えられた場合は、ステップ 13 へ。(これらの判定基準を満たす一つ以上のオブジェクト E が存在するならば、実装の裁量の一つを選択する)
  2. 新しい ECMAScript オブジェクトを生成し、 F をそのオブジェクトとする。
  3. F の [[Class]] プロパティを "Function" に設定する。
  4. F の [[Prototype]] プロパティを、セクション 15.3.3.1 に定義する、オリジナルの Function prototype オブジェクトに設定する。
  5. F の [[Call]] プロパティを、セクション 13.2.1 に述べるように設定する。
  6. F の [[Construct]] プロパティを、セクション 13.2.2 に述べるように設定する。
  7. F の [[Scope]] プロパティを、 Scope と同じオブジェクトで構成される新しいスコープ連鎖(10.1.4) に設定する。
  8. F の length プロパティを、FormalParameterList に指定される形式的プロパティの数に設定する。パラメータが指定されなければ、F の length プロパティを 0 に設定する。このプロパティは、セクション 15.3.5.1 に定義される属性を与えられる。
  9. new Object() により生成されるかのように、新しいオブジェクトを生成する。
  10. Result(9) の constructor プロパティを F に設定する。このプロパティは 属性 { DontEnum } を与えられる。
  11. F の prototype プロパティを Result(9) に設定する。このプロパティは、セクション 15.3.5.2 で定義される属性を与えられる。
  12. F を返す。
  13. 実装の裁量で、ステップ 2 またはステップ 14 へ。
  14. E に連結される、新しい Native ECMAScript オブジェクトを生成し、F をそのオブジェクトとする。全ての非内部プロパティが EF で一致するように、全ての非内部プロパティとその属性を E から F へ複写する。
  15. F の [[Class]] プロパティを "Function" に設定する。
  16. F の [[Prototype]] プロパティを、セクション 15.3.3.1 で定義するオリジナルの Function prototype オブジェクトに設定する。
  17. F の [[Call]] プロパティを、セクション 13.2.1 で述べるように設定する。
  18. F の [[Construct]] プロパティを、セクション 13.2.2 で述べるように設定する。
  19. F の [[Scope]] プロパティを、Scope と同じオブジェクトで構成されるむ新しいスコープ連鎖(10.1.4) に設定する。
  20. F を返す。

NOTE prototype プロパティは、各関数に自動的に生成され、関数がコンストラクタとして利用される可能性を許可する。

ステップ 1 は実装に、B が A に依存しないところの入れ子の関数 B を持つ関数 A の一般的なケースの最適化を許可する。このケースでは実装は B のために A が呼出される度に毎回新しいものを生成する代わりに同じオブジェクトの再利用を許可される。ステップ 13 はこの最適化を選択的にする; これを実装しないことを選択する実装は、ステップ 2 に進む。

例えば、このコード:

function A() {
  function B(x) {return x*x;}
  return B;
}

function C() {
  return eval("(function (x) {return x*x;})");
}

var b1 = A();
var b2 = A();
function  b3(x) {return x*x;}
function  b4(x) {return x*x;}
var b5 = C();
var b6 = C();

の中で、実装は、b1 と b2 の結合を許可される。だが要求はされない。実際、それらの [[Scope]] プロパティ間の違いを検知する方法がないので、b1 と b2 を同じオブジェクトに作成してもよい。一方、実装はソースコードの等しくない(13.1.1) b3 と b4 を結合してはならない。また実装は、2 つの異なる eval 呼び出しで生成されるためにソースコードの等しくない b5 と b6 も結合してはならない。

実際、それは、それらの [[Scope]] プロパティ間に違いが見られないことを実装が証明でき、それで 1 つのオブジェクトを再使用できる時にのみ、2 つの Function オブジェクトの結合に生産的だろう。このポリシーに従うことによって、実装は、それ自体に結合しているオブジェクトの空虚なケースに遭遇するだけになる。

13.2.1 [[Call]]

Function オブジェクト F の [[Call]] プロパティが呼出されるとき、次のステップが取られる:

  1. FFormalParameterList を用いる、新しい実行コンテキストを設置し、引数リストとセクション 10.2.3 で述べる this 値を渡す。
  2. FFunctionBody を評価する。
  3. 前の実行コンテキストを回復し、ステップ 1 で設置した実行コンテキストを出る。
  4. Result(2).type が throw ならば、Result(2).value を投げる。
  5. Result(2).type が ならば、Result(2) を返す。value を返す。
  6. (Result(2).type must be normal.) undefined を返す。

13.2.2 [[Construct]]

Function オブジェクト F の [[Construct]] プロパティが呼出されるとき、次のステップが取られる:

  1. 新しい Native ECMAScript オブジェクトを生成する。
  2. Result(1) の [[Class]] プロパティを "Object" に設定する。
  3. F の prototype プロパティの値を取得する。
  4. Result(3) がオブジェクトならば、Result(1) の [[Prototype]] プロパティを Result(3) に設定する。
  5. Result(3) がオブジェクトでなければ、Result(1) の [[Prototype]] プロパティを、セクション 15.2.3.1 で述べるオリジナルの Object prototype オブジェクトに設定する。
  6. F の [[Call]] プロパティを呼び出す。Result(1) を this 値として提供し、引数値として [[Construct]] に渡された引数リストを提供する。
  7. Type(Result(6)) が Object ならば、Result(6) を返す。
  8. Result(1) を返す。

Page Contents

Issued: / Revised: / All rights reserved. © 2002-2016 TAKI