JavaScriptの関数オブジェクトとは?

このQ&Aのポイント
  • JavaScriptの関数オブジェクトは、匿名関数から生成されます。
  • Callオブジェクトは関数の実行時に生成されるため、関数オブジェクトはコンパイル時に1回だけ生成されます。
  • クロージャについては、その都度関数オブジェクトが生成されるため、メモリ効率が悪いとされています。
回答を見る
  • ベストアンサー

JavaScriptの関数オブジェクト

JavaScriptの匿名関数から関数オブジェクトが作られるのはいつでしょうか。 ※ブラウザの実装によるかもしれませんが・・・ Callオブジェクトがその関数の実行時に毎回生成されるので、 処理コスト的に考えれば、関数オブジェクトはコンパイル時の1回だけで済むはずですよね? 関数コード自体はどんな呼び方しても共通なはずですから、 単に実行時に適切なCallオブジェクトをくっつけてあげるだけでいいはず・・・ (Functionコンストラクタ使うなら別でしょうけど) でも、クロージャについて「その都度、関数オブジェクトが生成されるのでメモリ効率が悪い」 という意見を割とあちこちのブログとかで見ます。 Callオブジェクトにでかいローカル変数が含まれると無駄、ってのなら分かるんですが。 このあたり、ECMAScriptの仕様では決められていない部分なのでしょうか。

  • mokpok
  • お礼率62% (154/245)

質問者が選んだベストアンサー

  • ベストアンサー
  • Chaire
  • ベストアンサー率60% (79/130)
回答No.8

あー、ごめんなさい。ご質問の意図を理解していませんでした。 ---- 以下の関数は、x の値によって戻り値が一意に決まります。構文は JavaScript 1.7 です。 (function(x) x + 1) (1); // 2 以下の関数は、x の値だけでは戻り値を予測できず、外部変数 a に左右されます。 var a = 1; (function(x) x + a) (1); // 2? 関数と、外部変数をセットにするのがクロージャです。この外部変数はこの関数でのみ使われます。 let(a = 1) (function(x) x + a) (1); // 2 しかし、let 式は現行の ECMAScript に存在しません。同じことを実現するには、関数をもう一つ使わねばなりません。これを私は「いわゆるクロージャ」と呼んでいます。 (function() { var a = 1; return function(x) { return x + a; } (1); }) (); 一応、関数に名前を付けてしまいましょう。 (function f() { var a = 1; return function g(x) { return x + a; } (1); }) (); --- さて、関数 g のローカル変数 x の値は、関数 g の呼び出しオブジェクトが知っています。これを Call_g とし、Callg["x"] によって x の値が分かるものとします。 しかし、外部変数 a に関しては、Call_g["a"] が存在しません。そこで、Call_g は関数 g に「あなたの文脈を教えてくれ」と頼みます(Call_g 自体は g の文脈を知りません)。関数 g は「私は関数 f を呼び出した Call_f によって作られた」と答えます。こうして、変数 a の値は Call_f["a"] で分かりました。 さて、No.5 のお礼で述べておられるように、クロージャが関数と変数束縛(すなわち Call オブジェクト)のセットであるのはその通りです。しかし、ここで Call オブジェクトが 2 種類あることに注意して下さい。すなわち、外部変数 a を束縛している Call_f と、ローカル変数 x を束縛している Call_g です。 もしこれが、関数 g と Call_g のセットであれば、仰る通り、メモリには何ら影響しないでしょう。しかし、ここで問題になっているクロージャとは、関数 g と Call_f のセットです。では、関数 g が Call_f を参照するには、どうすれば良いでしょうか。 ここで仮に、変数が変更不可で a = 1 が保証されるなら、関数 f を呼び出すたびに同じ関数 g を返しても構いません。しかし ECMAScript では変数 a を書き換えるような関数 g を返すこともできます。特定の変数 a、すなわち特定の Call_f とセットになる関数 g であるためには、ひとつの関数 g で複数の Call_f を管理するより、Call_f ごとに関数 g を生成した方が、結果的に安上がりではないでしょうか。 後は、個々の実装の最適化に委ねるのみです。

その他の回答 (7)

  • Chaire
  • ベストアンサー率60% (79/130)
回答No.7

No.5 お礼より: > その部分は仕様で定義されていない、というのが答えのようですね まず、「関数コード」というのは「FunctionBody として解析されるソースコード」であり、「入れ子のコードを含まない」(ES3: 10.1.2、ES5: 10.1)と定義されています。 「関数を生成する」とは、関数コードを呼び出すことができ、そのコード位置における実行コンテキスト(変数束縛済み)をスコープに含むようなオブジェクトを生成することです(ES3/5: 13.2)。 「関数コードの実行コンテキストに入る」とは、以下のようなことです。まず、関数コードを呼び出せる関数オブジェクトが、所与の引数リストと、関数コード内の宣言リストから、変数束縛を行います(ES5: 10.4.3, 10.5)。そして、関数コードを FunctionBody として評価した結果を返します(ES3/5: 13.2.1)。 ですから、ECMAScript 規定では、関数オブジェクトをコールするたびに、関数コードすなわち関数のソーステキストが評価される、と読めます。そして、関数コードに含まれる関数宣言と変数宣言が、実行コンテキストの変数束縛リストに含まれます。 --- しかしながら、上記はあくまで内部プロパティの説明です。内部プロパティとは、ECMAScript の振る舞いを説明するためのものであり、必ずしもそのように実装しろ、というものではありません。結果的に同じ振る舞いになれば、それで良いのです。 ここで、プログラムの意味論と、プログラムの実装を区別して下さい。ECMAScript という言語の意味論としては、実行コンテキストごとに(あるいは実行ステップごとに)新しい関数が生成されます。No.5 の最後の例で言えば、g1 != g2 でなければなりません。 そのことと、ECMAScript エンジンの実装は、別の話です。仮に g1 == g2 になるように実装しても、利用者の目には g1 != g2 であるかのように見えれば良いのです。 ES3 の結合オブジェクトの文言が ES5 で削除されたのは、意味論と実装とを混同しないようにするため、と見ることもできるかもしれません。 > コーディングの指針(クロージャの使用の是非、許される程度)が欲しくて そもそも、ECMAScript の関数型的な特徴を踏まえ、参照透過性を考慮すれば、いわゆるクロージャを単なるブロックのように使うことは避けるでしょうし、大きなクロージャでスパゲッティにならないよう関数を機能ごとに分割するでしょう(クロージャの濫用は、グローバル変数の濫用よりずっと性質の悪いものです)。 繰り返しますが、ECMAScript の意味論としては g1 != g2 です。同じ関数を何度も生成する(かのように見える)のを避けたければ、やりようはいろいろあるでしょうし、むしろその方が「良い」コードになりそうな気がします。

  • think49
  • ベストアンサー率59% (285/482)
回答No.6

#2 です。 JavaScriptコードをパース(構文解析)する話をされているのでしょうか。だとすれば読むのはこちらです。 http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/7_Lexical_Conventions.html http://es5.github.com/#x7-toc script要素の内容のパースは HTML5 (HTML Standard) の範疇になります。 http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#restrictions-for-contents-of-script-elements ただ、これはクロージャ云々よりずっと前の話です。 いわゆるクロージャは外部関数が [[Call]] された時に内部関数が実体化する過程で生まれますから、構文解析はとっくに終わっています。 また、コンパイルやメモリの仕組みは実装依存(ブラウザ依存)になります。 ECMAScript 仕様には「コンパイル」も「メモリ」も出てきません。 『JavaScript 第五版』は良い本ですが、便宜上の用語がいくつかあり、ECMAScript に出てくる用語とは違った表現になる場合があることに注意してください。 仕様理解に努めるなら、仕様書と比較しながら読み進めると良いと思います。

mokpok
質問者

お礼

ありがとうございます。 申し訳ありませんが、構文解析の話ではありません。 私の拙い言葉よりも、先にあげたURLの記事を読んで頂けると良さそうです。 その記事の内容が正しいのかどうかが気になっています。

  • Chaire
  • ベストアンサー率60% (79/130)
回答No.5

念のため、ご質問は『ECMAScript の仕様』でどうなっているかですので、それに沿って説明します。個々の実装については、それぞれのソースコードなどを確認して下さい。 --- No.3 お礼より: > 関数コードと、その実行コンテキストがセットであれば良いわけで それでは足りません。関数コードが「ソースコードのどこにあるか」が必要です。 function F(x) {  function G(y) {   return H(x + y);  }  function H(z) {   alert(z);  }  G(2); } F(1); // 3 ・Global の実行コンテキスト C0 に入る(F が実体化) ・関数 F の実行コンテキスト Cf に入る(Cf は C0 を参照、x と G と H が実体化) ・関数 G の実行コンテキスト Cg に入る(Cg は Cf を参照、y が実体化) ・関数 H の実行コンテキスト Ch に入る(Ch は Cf を参照、z が実体化) ・関数 G の実行コンテキスト Cg に戻る(Ch を廃棄) ・関数 F の実行コンテキスト Cf に戻る(Cg を廃棄) ・Global の実行コンテキスト C0 に戻る(Cf を廃棄) ここで、G から H の呼び出しにおいて、Ch が Cg を参照するのでなく(動的スコープ)、Cf を参照している(静的スコープ)ことに注意して下さい。これを実現するには、単に H が F の「関数コード」にアクセスできるだけでは駄目です。 一番手っ取り早いのは、F の実行コンテキスト Cf に入った時点で H を実体化し、H の内部プロパティ [[Scope]] に Cf をセットしてしまうことです。ですから、ECMAScript 3/5 の規定上は、実行コンテキストごとに「関数コード」から「関数オブジェクト」が生成されることになります。 --- 「変数(関数)の実体化」について、ECMAScript 規定にアルゴリズムの記載はあるものの、具体的な実装方法については範囲外です。一応、ECMAScript 5 のアルゴリズムでは、関数オブジェクトが内部プロパティ [[Code]] を持ち、関数の実体化は [[Code]] から関数を生成する、として説明されています。 あるいは、プログラムコードをいったん全部解析して抽象構文木でも構築すれば、関数オブジェクト自体の生成は一度で済むでしょう。しかしながら、上に書いたように、関数オブジェクトを実体化するには内部プロパティ [[Scope]] をセットする必要があります。そのため、構文木に属する「雛形としての関数オブジェクト」から、実行コンテキストごとにディープクローンを生成することになる、かもしれません。 --- 繰り返しますが、ECMAScript 3 には結合オブジェクトという規定があり、同じ位置・同じ関数コードで、内部プロパティだけが異なる関数オブジェクトであれば、ひとつにまとめて良い、ということになっていました。 function F(x) {  return function G(y) {   alert(x + y);  } } var g1 = F(1); var g2 = F(2); alert(g1 == g2); // 結合オブジェクトをサポートしているなら true しかし、この規定は ECMAScript 5 で削除されています。最適化については、それぞれの実装のソースコードを確認して下さい。 --- なお、window は DOM の一部ですので、ECMAScript では規定されていません(「例えば、HTML DOM では Global オブジェクトの window プロパティが Global 自身である」と言及があるだけ)。

参考URL:
http://web.archive.org/web/20061018193747/http://www.hawk.34sp.com/stdpls/jsnotes/jssinso/07_functions.html
mokpok
質問者

お礼

詳細な回答ありがとうございます。 今さらですが、私の用語の使い方が恐らく正しくないことについて謝罪します。 混乱させてしまい申し訳ありません。 例示されたソースコード、つまり静的スコープ(クロージャの性質)については、よく理解しています。 関数コードという表現が悪かったですね。 言いたかったのは、関数コードと静的スコープのセットです。 先に挙げたURLの言葉に沿うならば、関数オブジェクトとCallオブジェクトの雛型です。 これの生成は1回だけで良いだろう、ということを言いたかったのです。 ただどうやら、その部分は仕様で定義されていない、というのが答えのようですね。 コーディングの指針(クロージャの使用の是非、許される程度)が欲しくて、 実際に速度とメモリの効率にどんなロスがあるかを知りたかったのですが・・・ ブラウザの実装次第なのであれば、実際に問題が起きるまでは可読性・保守性重視でやるしかなさそうですね・・・

回答No.4

すみません、長くなりました。JavaScript以外の言語の表現を使います。(JavaScriptに概念がないため) >でも、クロージャについて「その都度、関数オブジェクトが生成されるのでメモリ効率が悪い」 クロージャはインスタンス内のプライベート変数です。 そのため(インスタンスを生成しなければならないため)、クロージャを使ったからといってメモリ効率が悪いとは言い切れないです。 newしてなくてもインスタンスというのは、他の言語のOOPと比較すると、めずらしいというか変に思われると思いますが。 function makeClosure(s,t){ var txt=s+'!'; var func=function(){ alert(txt); }; return function(){setTimeout( func, t ); }; } function main(){ var a=makeClosure('hello', 1000); var b=makeClosure('good', 2000); a(); //'hello' b(); //'good' } main(); 関数コードは1つでも、その内容はa、b別々に保持しておく必要があります。 変数a、bはmain()が終わると消滅しますが、 makeClosure内のtxtの寿命(スコープではなく)がメモリリークになる可能性があります。 ギリギリまで簡略化したものでも動的に関数オブジェクトを生成するかどうかというのは、ブラウザ依存だと思います。 function func(){ return true; /* var returnCode=true; return returnCode; と同じ。trueがクロージャになっている*/ } var a=func(); var b=func(); もしこの「メモリ効率が悪い」という言葉がシングルトンを意識してのものだとしたとしても、 JavaScriptでシングルトンは作れないようです。 >No.2 >console.log(hello1.print === javascript1.print); // false >console.log(hello2.print === javascript2.print); // true そんな違いがあったんですね。 単にメソッドがあるかどうかを検索する順番だけかと思ってましたが。。。 ということで、シングルトンを期待して作ってみましたが、、、 function func(){ this.txt='aiueo'; } func.prototype.count=0; func.prototype.increment=function(){this.count++;} alert('txt '+func.txt); // 期待'aiueo'、結果undefined //func.increment(); // 期待実行可、結果undefined(Exception) alert('func.count: '+func.count); // 期待0、結果undefined var n=new func(); n.increment(); alert('n.count: '+n.count); // 期待1、結果1 var b=new func(); b.increment(); alert('b.count: '+b.count); // 期待2、結果1 alert('n.count: '+n.count); // 期待2、結果1 alert('func.count: '+func.count); // 期待2、結果undefined 結果、シングルトンにはなりませんでした。 --------- RegExpは組み込み関数の中で唯一(だったはず)、シングルトンになっています。 var s='homepage-home'; var r1=new RegExp('(.+)-(.+)', ''); var r2=new RegExp('(www)', ''); s.match(r1); alert(RegExp.$1);// 'homepage'。r1.$1ではなくRegExpを使用する。 s.match(r2); // ヒットしない alert(RegExp.$1); // 'homepage'。r2がヒットしない場合は上書きされないため、r1の結果が残っている alert(RegExp.$2); // 'home'。r1の結果の$2 ----------------- windowというのはECMAScriptの「ルートオブジェクト」で定義されている物です。 グローバル変数のみ、varキーワードが付いていてもwindow配下のプロパティになります。 このルールもJavaScriptをややこしくしている原因かもしれません。 var a; // window.aと同等 function f(){ var b; // f.bではない } -------------------- 自称、似非シングルトン。(擬似ではなく似非。個人的にはこの方法を良く使います。) >単に実行時に適切なCallオブジェクトをくっつけてあげるだけでいいはず・・・ 勘違いしてたら済みません。たぶん、それっぽいことをしてるんじゃないかと、、、 var myObj=new (function(){  var txt='';  var interval=0;  this.makeClosure=function(s,t){   txt=s+'!';   interval=t;   return this;  };  this.alert=function(){ alert(txt); };  this.run=function(){   setTimeout( this.alert, interval );   return this;  }; })(); function main(){ var a=myObj.makeClosure('hello', 1000); var b=myObj.makeClosure('good', 2000); a.run(); // 'good' b.run(); // 'good' } main(); function main2(){ myObj.makeClosure('excelent', 1000).run(); // 'excelent' } //main2(); *setTimeoutから呼ばれたmyObj.alertの中では、thisの内容がwindowになるので、もしthis==myObjにしたかったら手を加える必要があります。

  • Chaire
  • ベストアンサー率60% (79/130)
回答No.3

ECMAScript における関数オブジェクトは次のように生成されます。 ・実行コンテキストと同時に生成される関数宣言 ・実行コンテキストを伴って実行されるコード中の関数式、Function 式。 ※「Call オブジェクト」と内部実装表現を書く参考書もありますが、ここでは ECMA 262 規定にある「実行コンテキスト」の用語を使います。 この中で「匿名」になりえるものは関数式しかありません。ということは、実行コンテキストごとに、かつ、コードの実行ステップごとに関数オブジェクトが生成されます。 > 関数オブジェクトはコンパイル時の1回だけで済むはず 関数オブジェクトはスコープチェーンを持つ必要がありますので、コンパイル時だけではチェックできません。スコープチェーンは、変数の実体化された実行コンテキストがないとセットできないからです(ここで、終了した実行コンテキストなのにスコープチェーンを解除できないバグが、いわゆるメモリリーク問題になりやすい)。 上に書いたように、関数宣言ならば実行コンテキストと同時に生成されます。また、コード実行時に評価される関数式をどうしても使わざるをえないなら、一度の生成で済むよう場所とスコープを工夫して下さい。 > 単に実行時に適切なCallオブジェクトをくっつけてあげるだけでいいはず ECMAScript 3 には「結合オブジェクト」(§13.1.2)として、ある種の条件が揃ったときに、まさにそのアイデアによってメモリを節約して良いことになっていました。しかし、NN6 ぐらいにしか実装されず、ECMAScript 5 で文言が削除されています。 --- ちなみに、ECMAScript 3 の正規表現リテラルは、プログラム開始時に 1 回だけコンパイルされます(§7.8.5)。つまり、プログラムコード中の正規表現リテラルは、実行コンテキストに関わらず同一である可能性があります(昔の Firefox、Opera)。ですから、g フラグ付きの正規表現リテラルを扱うときは十分に注意して下さい。正規表現オブジェクトのプロパティが書き換えられたまま、別の実行コンテキストに持ち越される可能性があるからです。 このことは、No.0 の仰る『関数オブジェクトはコンパイル時の1回だけで済むはず』と同じアイデアと言えます。ならば、同じような問題を抱える可能性があります。関数オブジェクトに付けたプロパティが、プログラム実行中に共有されてしまうことです(それはそれで便利かもしれませんが)。 正規表現リテラルに関するこの文言は ECMAScript 5 で削除されました。 --- 結論としては、仰るようなアイデアを無くす方向に ECMA 262 が修正されています。実装がそんなに簡単ではないからです。当面、必要ならばコンパイラの方で工夫してもらうことになります(だから、Google が Dart なんてものも出したわけで)。

mokpok
質問者

お礼

ありがとうございます。 > 関数オブジェクトはスコープチェーンを持つ必要がありますので、コンパイル時だけでは チェックできません。スコープチェーンは、変数の実体化された実行コンテキストがないとセットできないからです いえ、ですから、関数コードと、その実行コンテキストがセットであれば良いわけで、 関数コードは最初から最後まで変わりませんよね? 私の用語の使い方が間違っていたら申し訳ありません。 この最初から最後まで絶対に変わらない関数コードを、関数オブジェクトと表現し、 実行時に実行コンテキスト(Callオブジェクト)が作成され、 関数オブジェクトと合わせて実行されるのでは、という話です。 メモリ上に同じ関数コードがいくつも保持されるのでメモリが無駄、という話をよく見るので・・・ あとこんなページも見つけましたが、結局これは誤りということなのでしょうか。 http://fairy.ouchi.to/notes/2011/06/09-prog-a

  • think49
  • ベストアンサー率59% (285/482)
回答No.2

変数オブジェクトが実体化するタイミングを確認する事をお勧めします。 http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/10_Execution_Contexts.html#section-10.1.3 --- function Hello1 (string) {  this.string = string;  this.print = function () { return '"' + this.string + '"'; }; } function Hello2 (string) {  this.string = string; } Hello2.prototype.print = function () { return '"' + this.string + '"'; }; var hello1 = new Hello1('Hello, World!'), javascript1 = new Hello1('Hello, JavaScript!'), hello2 = new Hello2('Hello, World!'), javascript2 = new Hello2('Hello, JavaScript!'); console.log(hello1.print === javascript1.print); // false console.log(hello2.print === javascript2.print); // true --- Hello1#print はコンストラクタ呼び出しされる度に新しい関数オブジェクトを生成します。 対して、Hello2#print はプロトタイプチェーンを辿って同じ関数オブジェクトを参照します。(つまり、メモリ効率が良い) 私はコンパイラ型言語に詳しくありませんが、「関数オブジェクトはコンパイル時の1回だけで済むはず」は ECMAScript においては当てはまりません。(そもそも、JavaScriptはインタプリタ言語です…。) FunctionDeclaration と FunctionExpression で評価するタイミングが異なりますし、関数コードにおいて変数が実体化されるのは該当変数の上位にある関数が [[Call]] された時です。

mokpok
質問者

お礼

ありがとうございます。 確かにこの例のような説明をあちこちで見ます。 ただ、JavaScriptがインタプリタ言語であることは知っていますが、 コンパイルという表現も割と使われているので、実行時のコード変換?を指すと思っていました。 http://fairy.ouchi.to/notes/2011/06/09-prog-a ここの内容は誤りということでしょうか。

  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.1

以下のコードで「function(){alert(text);}」は1箇所にしか書かれていませんが、 その実体であるfunc_aとfunc_bは別物になります。 function get_function(text){ return function(){alert(text);} } var func_a = get_function("a"); var func_b = get_function("b"); func_a(); //→a func_b(); //→b alert(func_a===func_b); //→false

mokpok
質問者

お礼

ありがとうございます。 その説明自体はよく見るので分かっています。 この質問は、本当にそうなの?という話です。

関連するQ&A

  • javascriptのコードについて

    以下のコードなのですが、 エンクロージャー関数の ローカル変数hogeをさらに、エンクロージャー内部で定義された 関数ででクロージャーとして保持させたいメソッドのコードですが var Method = function (){ var hoge = "初期値"; var getter = function (){ return hoge; } var setter = function (param){ hoge = param; return hoge; } return {"set" : setter,"get" : getter} } var obj = Method(); console.log(obj); console.log(obj . get()); obj.set("初期値変更"); console.log(obj.get()); obj . set("更に変更"); console.log(obj.get()); この場合、メソッドの返り値として、一般的な文献に乗っている関数(関数オブジェクト)を返すのではなく オブジェクトリテラルとして返しています。 この場合でも、動きとしてはクロージャーの動きをしているのでhogeという変数の保持はできているっぽいんですが クロージャーって関数内で定義された関数であれば、どういう返り値の返し方でも クロージャーになるのですかね? また、この方法は、一般的にjsで関数コンストラクタ呼び出しをしてインスタンスを作る際privateメンバを実現する方法として紹介されていますが、 これはクロージャーとして生成するたんびに内部の変数を保持するためメモリ食い虫になるらしいのですが まず間違いなく、このクラス(便宜上そう呼びます)のインスタンスはひとつしかつくることはない!!という仕様だとしても いけないのでしょうか? というかもう現状javascripのバッドノウハウ的なものになっているのでしょうか?

  • 用語/newを伴わないコンストラクタの呼出=関数?

    コンストラクタを勉強しているのですが、「用語」「意味」が分からないので、教えてください ■質問1 ・いついかなる時でも、「コンストラクタ関数」=「コンストラクタ」=「関数」=「メソッド」なのでしょうか? ・例えば、「newをつけずに、コンストラクタを関数として呼ぶ」場合も、「コンストラクタを実行する」と言うのでしょうか? ■質問2 … 「new」付与による相違 ・「new」付与しないと、「コンストラクタ」内で「this」が指し示す対象が異なる(グローバルオブジェクトになってしまう)のだと思うのですが、それ以外に何か相違点はあるのでしょうか? ・「new」付与しないとオブジェクトが正しく生成されないので、不具合が生じる可能性がある? ■質問3 ・「new」を付けずに、オブジェクトを関数として実行するのは、例えばどういう使い方をするときなのでしょうか?

  • 自作関数におけるコンストラクタとデストラクタ

    お世話になります。 定義クラスにおいて、オブジェクト生成時と解放時にコールされる関数(__construct()、__destruct())は有名ですが、クラス内に定義した自作関数がコールされた時と終了(?)した時に、コールされる関数は存在するのでしょうか。 現在、自作した関数の最初と最後に、ログ書き込み用の自作関数を仕込む事で、希望した挙動を実装していますが、自作関数におけるコンストラクタ、デストラクタの様な関数があれば楽かなと、色々検索したのですが、今ひとつヒットしませんでした。 ご存じの方、情報提供頂ければ嬉しいです。

    • 締切済み
    • PHP
  • クロージャ

    javascriptのクロージャについて。 クロージャにnewは必要ですか? コンストラクタであれば、newでオブジェクトを生成しますが、クロージャはどうでしょうか? クロージャ-------------------- function Person(n, a){ var name = n; var age = a; return { getName: function() { return name; }, setAge: function(i){ if( 0<= i ){ age = i; } }, getAge: function(){ return age; } } } var p = new Person('Hanako', 3); // new を付けなくても生成できる

  • イベントリスナに登録される function(e){} の "e" はeventオブジェクト?

    私はイベントリスナ登録時の匿名関数に渡す引数eの意味が今まで理解できていませんでした。 最近、下記コードを実行することで、 <script type='text/javascript'> window.addEventListener ('click', function(e){ console.info(e); // 引数をコンソール表示 (要Firebug) for (p in e){ console.info(p + ' = ' + e[p]); // プロパティを列挙 } }, false); </script> 「eventオブジェクトを渡しているらしい」と朧気ながら理解できました。 ただ、疑問点も残ります。 私の理解では、匿名関数は (function(str){ alert(str); })('Hello'); のように明示的に引数を渡さなければ、引き渡された値は undefined となるはずでした。 変数eの値はどこから出現したのでしょうか? そもそも、変数eはeventオブジェクトなのでしょうか?

  • Linux(g++)とAIX(XL C++)の挙動の違いについて

    以下のプログラムをg++とXL C++でコンパイルした場合に差異が生じており、困っています。 ========================================================= #include <stdio.h> #include <stdlib.h> class Abc { public: Abc() { printf("コンストラクタCall\n"); } void print() { printf("メソッドCall\n"); } }; Abc abc; int main() { abc.print(); return 0; } ========================================================= 上記のようなソースの場合、g++でコンパイルしたものはメソッドがコールされる前にコンストラクタもコールされています。 しかし、XL C++でコンパイルするとコンストラクタはコールされるメソッドのみのコールとなります。 XL C++をg++の挙動と合わせたいのですが、コンパイル時のパラメータ設定等で解消できるものでしょうか? 御存知の方がいらっしゃいましたらよろしくお願い致します。

  • 【jquery】即時関数について

    知識のある方に教えて頂きたく、貴重なスペースをお借りいたします。 $(function(){ })と、即時関数の(function(){})();は 何が異なるのでしょうか。 よくグローバルオブジェクトの汚染を防ぐ為に 即時関数を使用すると記載がありますが、 通常JSを記載する際に使用する、DOM構築後に実行をする記述 $(function(){ })も、結局変数などをVar宣言すれば、 ローカル変数になるので、同じこと(グローバルの汚染を防げる) ではないかと思うのですが、間違っておりますでしょうか。 それだとすると、即時関数の使い道がわからないのですが、 ご教示頂けますでしょうか。 また、以下の(1)の記述方法だと、 「hoge」はグローバルオブジェクトとなってしまいますが、 (2)だとなりませんよね。 であれば、基本的には(2)のように関数は記載した方が良いのでは ないのでしょうか。結構(1)の書き方をしている方がいるので。 どなたかご教示いただければ幸いです。 よろしくお願いいたします。 ----------------------- (1) $(function(){ hoge(); }) function hoge(){ return true; } ----------------------- ----------------------- (2) $(function(){ hoge(); function hoge(){  return true; } }) -----------------------

  • オブジェクトに新しい関数を追加したい。

    いつもお世話になってます! このサイトでいろいろと勉強させて頂いています! 表題の通り、あるオブジェクトに新しい関数を追加したいですが、書き方が悪いのかうまく行きません。 例えば、変数名canvasというdivオブジェクトを生成したとします。 var canvas = document.createElement('div'); このcanvasにline(start_x,start_y,end_x,end_y)なんて線を描く関数を付けたいな…と思ったのです。 理想として、以下のような書き方がしたいのです。 var canvas = document.createElement('div'); canvas.setSize(0,0,600,400); // divのサイズ canvas.setColor(255,0,0); // 色決め canvas.line(0,0,100,100); // (0,0)~(100,100)に線を引く。 document.appendChild(canvas); こんな事、可能でしょうか? また、documentに対してこのような関数を追加したりする事は可能でしょうか? お時間がある時にでも教えていただければと思います。

  • obj オブジェクトファイルができる?

    VB6で、デザイン時や、コンパイル時に、 オブジェクトファイル(*.obj)が生成される事がありますか? よろしくお願いします。

  • オブジェクト指向について質問

    メインのクラスをインスタンスする際にコンストラクターに書かれている処理が実行されますが、オブジェクトが生成された時のイベントに書くのと、どのような違いがありますか? public partial class Form1 : Form{ public Form1()//コンストラクター {処理1} private void Form1_Load(object sender, EventArgs e)//インスタンス時のイベント {処理2} } また、別クラスの中でnewを使ってインスタンスがされ場合、コンストラクターと上記のイベントは同じように発生しますか? public class Form2{ Form1 = new Form1(); } よろしくおねがいします。

専門家に質問してみよう