Home > JavaScript

JavaScript Archive

JavaScript 第 5 版 8 章まとめ

ようやく 8 章まで来ました。
だいぶ内容が難しくなってきたので、読んでもよく分からないものはちゃんと手を動かして理解するように心がけました。
ですが、最後のクロージャのところは正直理解できませんでした・・・。また後で読んでみます。

8 章 関数

8.1.1 入れ子型の関数

  • 関数を他の関数の中に入れ子で定義できる。
  • ただし入れ子にする関数のトップレベルで定義しなければいけない。if 文の中などでは定義できない。

8.1.2 関数リテラル

var f = function() { return x * x };  // 変数に格納したり
f[0] = function(x) { return x * x };  // 配列要素に格納したり
a.sort(function(a, b) { return a - b; });  // 別の関数に渡したり
var s = (function(x) { return x * x; })(10);  // 定義してすぐに呼び出したり

8.2.1 省略可能な引数

  • 関数を定義した時よりも少ない数の引数でその関数を呼び出した場合、省略された引数には undefined が設定される。
  • この特徴を利用して、省略可能な引数を持つ関数を定義できる。
  • ただしその際には、関数内で引数が省略された場合にデフォルト値が設定されるように処理する必要がある。
  • また、省略可能な引数は引数リストの最後に記述する必要がある。

function f(o, a) {  // a は省略可能とする
  a = a || [];  // a が省略されている場合は空の配列を生成
  for(var p in o) a.push(p);
  return a;
}

8.2.2 可変長の引数リスト(Arguments オブジェクト)

  • Arguments オブジェクトは配列のようなオブジェクトである。
  • 関数に渡された引数値は、関数定義値の引数に関わらず arguments[] 配列の要素に格納される。
  • function f(x, y, z) {
    	return arguments.length;
    }
    f(1, 2, 3);  // 3
    f(1);  // 1
    f(1, 2, 3, 4, 5);  // 5。関数定義時の引数の個数に関わらず、任意の数の引数値を渡せる。
    
    function max() {  // 引数を定義しない
      var m = Number.NEGATIVE_INFINITY;
      for(var i = 0; i < arguments.length; i++) {
      	if(arguments[i] > m) m = arguments[i];
      }
      return m;
    }
    max(1, 10, 2, 3000, 400);

  • 関数の引数を格納するローカル変数と Arguments オブジェクトの配列の要素は同じ値を保持する。
  • function f(x) {
      alert(x);  // 渡された引数値を表示
      arguments[0] = null;
      alert(x);  // null
    }

8.2.2.1 callee プロパティ

  • Arguments オブジェクトの callee プロパティは、現在実行中の関数を参照する。
  • 再帰処理を行う関数などで使用される。

function f(x) {
  if(x < = 1) return 1;
  return x * arguments.callee(x - 1);
}
f(5);

8.2.4 引数の型

  • JavaScript は弱い型付き言語で、関数定義時に引数の型を宣言することはできないので、型を限定する場合は関数内で型のチェックを行う必要がある。

8.4 メソッドとしての関数

  • 関数がメソッドとして呼び出された場合、this キーワードは呼び出されたオブジェクトを参照する。
  • 関数がメソッドではなく関数として呼び出された場合、this キーワードはグローバルオブジェクトを参照する。

var f = function() { return this; };
f();  // 関数として呼び出し。Window オブジェクトが返る。

var o = { f: function() { return this; }};
o.f();  // メソッドとして呼び出し。o オブジェクトが返る。

var a = [];
var o = {
  f: function() {
    function g() { a.push(this); }
    g();
    a.push(this);
  }
}
o.f();
alert(a[0]);  // メソッドとして呼び出された関数内の入れ子関数として呼び出し。Window オブジェクトが表示される。
alert(a[1]);  // メソッドとして呼び出し。o オブジェクトが表示される。

8.6 関数のプロパティとメソッド

  • 関数は、実際には特殊なオブジェクトであるため、プロパティやメソッドを持つ。

8.6.1 length プロパティ

  • Function オブジェクトの length プロパティには引数リストで宣言された引数の個数が設定される。
  • arguments.length プロパティと異なり、関数の外でも使用できる。

// 宣言時の引数の個数と呼び出し時の引数の個数が一致していれば true を返す
// arguments.callee.length は check.length でも可
function check(a) {
  return (arguments.length == arguments.callee.length);
}
check(1);  // true
check(1, 2);  // false
check();  // false

8.6.3 自分専用の関数プロパティの定義

  • Function オブジェクトのプロパティであれば関数の実行を終了した後も値を保持し、次に関数が呼び出された時に使うことができる。

uniqueInteger.counter = 0;
function uniqueInteger() {
  return uniqueInteger++;
}
uniqueInteger();  // 0
uniqueInteger();  // 1

8.6.4 apply() メソッドと call() メソッド

  • あるオブジェクトのメソッドであるかのように関数を呼び出すことができる。
  • 最初の引数に呼び出す関数の対象となるオブジェクトを指定する。
  • call() メソッドの 2 番目以降の引数は、これから呼び出される関数に引数として渡される。
  • apply() メソッドの場合は、第 2 引数に関数に渡す引数を配列形式で指定する。

var f = function(a, b) { alert(a * b); return this; };
f(1, 2);  // Window オブジェクトが返る
var o = {};
f.call(o, 1, 2);  // o オブジェクトが返る。メソッドとして実行されている。
f.apply(o, [1, 2]);  //       〃

8.8.1 静的なスコープ

  • JavaScript 関数のスコープは、実行時のスコープではなく定義時のスコープという意味で、静的である。
  • 関数が定義されると、定義された関数の内部状態に、現在のスコープチェーンが保存される。
  • 関数を入れ子で定義する場合は、スコープチェーンには入れ子関数の外側の関数が含まれる。

8.8.2 Call オブジェクト

  • JavaScript インタプリタは関数が呼び出されると、関数のスコープにまず関数定義時のスコープチェーンを設定し、次に Call オブジェクトをスコープチェーンの先頭に追加する。
  • arguments やローカル変数、仮引数は Call オブジェクトのプロパティになる。

8.8.3 名前空間としての Call オブジェクト

  • Call オブジェクトを一時的な名前空間として使えば、グローバルな名前空間での変数名やプロパティ名の衝突を避けることができる。

8.9 Function() コンストラクタ

  • Function() コンストラクタを使うと、JavaScript のコードを実行時に動的に生成してコンパイルできる。
  • Function() コンストラクタを使うたびに、関数の本体が解釈され新しい関数オブジェクトが生成される。
  • そのため、頻繁に呼び出される関数やループで使用すると、効率が悪くなる。

function f(x, y) { return x * y; }
var f = new Function("x", "y", "return x * y;");  // 上記関数文を Function() コンストラクタを使用した形で記述

JavaScript 第 5 版 7 章まとめ

今回はボリューム多め。
この章で、今まであまり馴染みがなかった Object クラスのメソッドと、しっかり把握できていなかった配列のメソッドを抑えられたと思います。

7 章 オブジェクトと配列

7.1 オブジェクトの生成

  • {}(オブジェクトリテラル)と new 演算子を使ってコンストラクタ関数を呼び出して生成する方法がある。
  • {} と new Object() は同じ意味となる。
  • {} の中に、プロパティ名と値のペアをカンマ区切りで記述する。
  • プロパティ名には識別子または文字列が使用できる。

var obj1 = {};
var obj2 = new Array();  // Array オブジェクトを生成する
var obj3 = {
  "name": "hoge",
  'value': 1,
  obj: {x: 0, y: 0}
};

7.2 オブジェクトのプロパティ

  • var の宣言は不要で、オブジェクトのプロパティに値を代入することでプロパティを生成できる。

7.2.1 オブジェクトプロパティの調査

  • for/in ループでユーザ定義のプロパティを調べられる。

var obj = {
  name: "hoge",
  value: 1
};
var s = "";
for(var o in obj) {
  s += o + " : " + obj[o] + "¥n";
}
alert(s);

7.2.2 プロパティの存在確認

  • in 演算子を使ってプロパティが存在するかどうかを調べられる。
  • var o = {x: 0};
    if("x" in o) o.x = 1;
    alert(o.x);  // 1

  • in 演算子を使わなくても実現できる。ただし o.x = undefined (プロパティ自体は存在していて値が未定義値)の場合は正しい結果にならないので注意する。
  • var o = {x: 0};
    if(o.x !== undefined) o.x = 1;
    alert(o.x);

  • undefined でも null でもない場合は以下の記述で実現できる。
  • var o = {x: 0};
    if(o.x) alert("hoge");

7.2.3 プロパティの削除

  • delete 演算子で削除できる。
  • undefined が設定されるのではなくプロパティが削除されるので、for/in ループでも調べられなくなる。

var o = {x: 0, y: 0};
delete o.x;
var s = "";
for(var i in o) {
  s += i + "¥n";
}
alert(s);  // y¥n

7.3 連想配列としてのオブジェクト

  • オブジェクトのプロパティにアクセスするには、ドット演算子の他に “[]“(配列演算子)を使ってアクセスできる(連想配列とも呼ばれる)。
  • 配列演算子を使用した場合、実行中に生成することができる。

var addr = "";
for(var i = 0; i < 4; i++) {
  addr += customer["address" + i] + "¥n";  // customer オブジェクトの address0 〜 3 プロパティの値を読み出せる
}

7.4 Object のプロパティとメソッド

  • 全てのオブジェクト(Array() や Date() も含めて)は Object クラスのプロパティやメソッドを継承する。

7.4.1 constructor プロパティ

  • オブジェクトの初期化で使用されたコンストラクタ関数を参照する。
  • instanceof 演算子で constructor プロパティの値を調べられる。
  • ※Safari(というか Webkit)ではバグがあるらしく、false になりました。

var d = new Date();
alert(d.constructor == Date);  // true
alert(d instanceof Date);  // true

7.4.2 toString() メソッド

  • 呼び出したオブジェクトの値を表す文字列を返す。

7.4.3 toLocaleString() メソッド

  • オブジェクトを表すローカライズされた文字列を返す。

7.4.4 valueOf() メソッド

  • オブジェクトを文字列以外の基本型(数値型が多い)に変換する。

7.4.5 hasOwnProperty() メソッド

  • 継承したものではないプロパティを持つ場合に true を返す。

7.4.6 propertyIsEnumerable() メソッド

  • 継承したものではないプロパティを持ち、かつそのプロパティが for/in ループで調べられる場合に true を返す。
  • hasOwnProperty() メソッドと同じ値を返す。

Continue reading

JavaScript 第 5 版 6 章まとめ

6 章 文

6.5 switch 文

  • switch 文は式の値と同値演算子 (===) で比較し、値が一致する case ラベルを上から順に探す。
  • case 句は実行するコードの開始点を示すだけなので、その後ろの case ラベルのコードブロックを実行したくない場合(ほとんどですが)は break 文を記述する必要がある。

6.11 break 文

  • 最も内側のループまたは switch 文を直ちに終了する。
  • break キーワードの後にラベル名を指定すると、ラベルで指定された文の最後に処理が移動される。

6.12 continue 文

  • ループ中で使用し、次の繰り返しからループの処理を再開する。
  • while ループの場合は、条件式を再テストし、その結果が true であればループを実行する。
  • for ループの場合は、インクリメント式を評価してから条件式を再テストし、次の繰り返し処理へ進むかどうかが判定される。
  • for/in ループの場合は、指定された変数に代入された次のプロパティ名から処理が再開される。

6.14 function 文

  • function 文による関数定義は、関数を定義するだけであり、コンパイルされた時点で関数文が実行されるわけではない。

alert(f(4));  // 16 が表示される。この文が実行される時点では f 関数が定義済。
var f = 0;  // プロパティ f の値を上書きする
function f(x) {  // 関数 f の定義は上記文より先に行われる
  return x * x;
}
alert(f);  // f は 0 に上書きされているので 0 が表示される

6.16 throw 文

  • throw 文を記述すると例外がスローされる。
  • 例外がスローされると、最も近い例外ハンドラに処理を移動する。
  • 例外ハンドラは try/catch/finally 文を使って catch 句に記述する。
  • 例外がスローされたコードブロックに catch 句がない場合は、さらに上位のコードブロックに catch 句がないかを調べる。
  • 例外ハンドラが見つからなかった場合は、例外はエラーとしてユーザに報告される。

6.17 try/catch/finally 文

  • try 句には例外処理の対象となるコードブロックを記述する。
  • catch 句には try ブロック内で例外が発生した時に呼び出される文を記述する。
  • finally 句に記述したコードは、try 句の処理が終了した後に必ず実行される。
  • try ブロックのコードが一部でも実行されれば、finally ブロックのコードも必ず実行される。
  • try ブロック中で例外が発生した場合も、catch ブロックのコードが実行された後 finally ブロックのコードが実行される。

6.18 with 文

  • with 文が実行されると指定されたオブジェクトがスコープチェーンに追加される。
  • 実行後には、スコープチェーンは元の状態に戻る。
  • ただし、実行速度が遅くなったり、with 文の本体に関数定義と変数の初期値設定がある場合、思いがけない振る舞いが起きることがあるため、使用は控えた方が良い。
  • 以下のコードの場合、o のプロパティ p を表示することを想定しているが、もしそのプロパティが存在しなかった場合、エラーにならずに f 関数の仮引数である p が使用されてしまうからという意味?

function f(o, p) {
  with(o) {
    alert(p);
  }
}
var o = {p: 0};
f(o, 1);  // o のプロパティ p の値 0 が表示される
delete o.p;
f(o, 1);  // o には p プロパティが存在しないため f 関数の仮引数 p の値 1 が表示される

参考リンク

JavaScript 第 5 版 5 章まとめ

引き続きサイ本のまとめ。5 章の前半は基礎的なものなので斜め読み。

5 章 式と演算子

5.5.1 比較演算子

  • 比較は数値と文字列のどちらかで行われる。数値でも文字列でもないものはそのどちらかに変換される。
  • 文字列の比較は Unicode の文字コード値を使って、アルファベット順で比較される。

5.5.2 in 演算子

  • 左側の値が右側のオブジェクトのプロパティ名であれば true を返す。
  • なお、左側の値は文字列か文字列に変換されるものでなければならないので注意。

var o = { x : 1, y : 1 };
alert("x" in o);  // true
alert(x in o);  // false
alert("z" in o);  // false

5.5.3 instanceof 演算子

  • 左側のオブジェクトが右側のクラスのインスタンスであれば true を返す。

var d = new Date();
alert(d instanceof Date);  // true(Safari では false。なぜ?)

5.7.1 論理積演算子(&&)

  • 左側のオペランドと右側のオペランドの両方が true の場合に true を返す。
  • ただし内部的には、まず左側のオペランドを評価して false に変換できる場合は左側の式の評価結果を返し、それ以外の場合は右側のオペランドの評価結果を返す。
  • よって、右側の式は必ず評価されるわけではないので、代入やインクリメンタルを右側のオペランドで使うと意図しない動作になることがある。

var a = 0, b = 1;
(a == b) && alert("equal");  // alert は表示されず、false が返される
(a != b) && alert("not equal");  // alert が表示される

5.7.2 論理和演算子(||)

  • 左側のオペランドと右側のオペランドのどちらか一方または両方が true の場合に true を返す。
  • 内部的には論理積演算子と同じような振る舞いをする。

5.10.3 オブジェクト生成演算子(new)

  • まず、プロパティを定義せずに新しいオブジェクトを生成する。
  • 次に、指定されたコンストラクタ関数を呼び出し、指定された引数を渡す。
  • 新たに生成されたオブジェクトを this キーワードの値に代入する。

5.10.4 delete 演算子

  • オペランドに指定されたオブジェクトのプロパティや配列の要素、変数を削除する。
  • コアに組み込まれたプロパティやクライアントサイドのプロパティの一部には削除できないものがある。
  • var 文で宣言された変数は削除できない。
  • プロパティや変数、配列の要素を削除した場合、未定義値が代入されるわけではなくプロパティは存在しなくなる。

5.10.5 void 演算子

  • オペランド値を破棄し未定義値を返す。

JavaScript 第 5 版 4 章まとめ

4 章 変数

4.2 変数の宣言

  • 変数は必ず var で宣言する。宣言せずに値を代入した場合、その変数はグローバル変数になる。
  • var で変数の初期値を設定しなかった場合は値が代入されるまで undefined になる。
  • var で宣言された変数は永続され、delete 演算子で削除できない。

4.3 変数のスコープ

  • グローバル変数のスコープはプログラム全体。
  • ローカル変数のスコープはその変数が宣言された関数の中。
  • 関数の中にグローバル変数と同じ名前のローカル変数があった場合はローカル変数が優先され、グローバル変数は隠される。

var scope = "global";  // グローバル変数
function checkScope() {
  var scope = "local";  // ローカル変数
  alert(scope);
}
checkScope();  // "local"
alert(scope);  // "global"

scope = "global";  // グローバル変数
function checkScope() {
	scope = "local";  // グローバル変数の値を変更
}
checkScope();
alert(scope);  // "local"

var scope = "global";
function checkScope() {
  alert(scope);  // "global" ではなく undefined
  var scope = "local";
  alert(scope);  // "local"
}

4.3.1 ブロックレベルのスコープはない

  • ある関数で宣言された変数は、どのブロックで宣言されたのにかかわらず関数全体で有効である。

// i, j, k は scope 関数内で有効である
function scope() {
  var i = 0;
  for(var j = 0; j < 5; j++) {
    document.write(j);
    for(var k = 0; k < 5; k++) {
      document.write(k);
    }
  }
}

4.5 ガーベジコレクション

  • JavaScript インタプリタは、オブジェクトが不要になったと判定したら、オブジェクトが使用していたメモリを解放する。

4.6 プロパティと変数は違うのか

  • オブジェクトのプロパティと変数は基本的に同じである。

4.6.1 グローバルオブジェクト

  • JavaScript インタプリタは、コードの実行前にグローバルオブジェクトを生成する。
  • グローバル変数とはグローバルオブジェクトのプロパティである。
  • トップレベルコードでは、this はグローバルオブジェクトを参照する。
  • クライアントサイド JavaScript でのグローバルオブジェクトは Window オブジェクトである。

4.6.2 ローカル変数は Call オブジェクトのプロパティ

  • ローカル変数とは Call オブジェクトのプロパティである。

4.6.3 JavaScript の実行コンテキスト

  • JavaScript インタプリタは個々の関数を実行するたびに、新しい実行コンテキストを生成する。
  • 関数外部のコードの実行コンテキストでは、グローバルオブジェクトが変数定義に使用される。
  • 関数内部のコードの実行コンテキストでは、Call オブジェクトが変数定義に使用される。
  • 実装によっては、複数のグローバル実行コンテキストが認められている場合がある(クライアントサイド JavaScript で、ウィンドウがフレームで分割されている場合など)。
  • 複数のグローバル実行コンテキスト間で相互に参照できるが、これはセキュリティ上の脅威になりうる。

4.7 変数のスコープの再検討

  • 実行コンテキストには、それぞれのコンテキスト毎にスコープチェーンがある。
  • スコープチェーンとは、グローバルオブジェクトや Call オブジェクトを並べたもの。
  • 変数 x の値を探す時は、スコープチェーンの先頭のオブジェクトから x という名前のプロパティがあるかどうかを確かめる。
  • 無ければ次のオブジェクトで探索を続け、見つかるまで探索する。
  • 全てのオブジェクトでそのプロパティが存在しない場合は undefined になる。
  • 下記のコードで g() 関数内で変数 x の値を探す場合、まず g() の Call オブジェクトのプロパティを探し、無ければ f() の Call オブジェクト、グローバルオブジェクトの順に探索し、グローバルオブジェクトのプロパティ x の値を返す。
  • var x = 1;
    function f() {
      var y = 2;
      function g() {
        var z = 3;
        alert(x);
      }
      g();
    }
    f();

 Page 2 of 3 « 1  2  3 »

ホーム > JavaScript

Search
Feeds
Meta
あわせて読みたい
あわせて読みたいブログパーツ
Others...
フィードメーター - sukechan.net
track feed

Return to page top