シェイクスピアはかつて言った:「良い記憶よりも悪いメモの方が良い。」
第 1 章 JavaScript の紹介#
1.1 JavaScript の簡単な歴史#
1.2 JavaScript の実装#
-
完全な JavaScript の実装は、3 つの異なる部分から構成されるべきです:コア(ECMAScript)、ドキュメントオブジェクトモデル(DOM)、ブラウザオブジェクトモデル(BOM)。
-
ECMAScript:コア言語機能を提供します;DOM:ウェブページの内容にアクセスし操作するための方法とインターフェースを提供します;BOM:ブラウザと対話するための方法とインターフェースを提供します。
1.3 JavaScript のバージョン#
第 2 章 HTML での JavaScript の使用#
2.1 script 要素#
-
タグの位置:ブラウザがページを表示する際に明らかな遅延を避けるために、現代の Web アプリケーションは一般的にすべての JavaScript の参照を <body> 要素のページ内容の後ろに置きます。
-
遅延スクリプト:defer 属性は、スクリプトの実行がページの構造に影響を与えないことを示し、スクリプトはページ全体が解析された後に実行されます;外部スクリプトファイルにのみ適用されます。
<script defer="defer" src="example.js"></script>
- 非同期スクリプト:async 属性は、現在のスクリプトが他のスクリプトを待つ必要がなく、ドキュメントの表示をブロックする必要がないことを示し、ブラウザにファイルを即座にダウンロードするように指示します。また、async としてマークされたスクリプトがその順序で実行されることは保証されません;外部スクリプトファイルにのみ適用されます。
<script async src="example1.js"></script>
<script async src="example2.js"></script>
2.2 埋め込みコードと外部ファイル#
2.3 ドキュメントモード#
- 混合モードと標準モード;標準モードを有効にする:
<!-- HTML 5 -->
<!DOCTYPE html>
2.4 noscript 要素#
第 3 章 基本概念#
3.1 構文#
-
大文字と小文字の区別:ECMAScript のすべては大文字と小文字を区別します。
-
厳格モード:厳格モードでは、ECMAScript 3 のいくつかの不確実な動作が処理され、特定の安全でない操作に対してもエラーがスローされます。トップに次のコードを追加します:
"use strict"
3.2 キーワードと予約語#
3.3 変数#
- 宣言されていない変数に値を割り当てると、厳格モードでは ReferenceError エラーが発生します。
3.4 データ型#
-
typeof 演算子は、変数のデータ型を検出するために使用されます。
-
5 つの基本データ型:Undefined、Null、Boolean、Number、String;1 つの複雑データ型(参照型):Object。
-
Undefined 型:var で変数を宣言したが初期化しなかった場合、その変数の値は undefined です。
-
Null 型:null 値は空のオブジェクトポインタを示します;オブジェクトを保存する意図のある変数がまだ実際にオブジェクトを保存していない場合、その変数に明示的に null 値を保存する必要があります。
-
Boolean 型:他の型を Boolean 型に変換するには、Boolean () 関数を使用します。
-
Number 型:他の型を Number 型に変換するには、一般的に parseInt () 関数を使用します。文字列を変換する際、最初の文字が数字の文字または負号でない場合、NaN が返されます。第二の引数はオプションで、基数を示します。
-
String 型:文字列は不変です;他の型を String 型に変換するには、toString () または String () 関数を使用するか、空の文字列(1+'')を追加します。
-
Object 型
オブジェクトを作成する方法:
var o = new Object();
Object オブジェクトのインスタンスを作成し、そのプロパティやメソッドを追加することで、カスタムオブジェクトを作成できます;
Object 型はすべてのインスタンスの基礎であり、以下のプロパティとメソッドを持っています:
-
constructor:現在のオブジェクトを作成するための関数、すなわちコンストラクタを保持します;
-
hasOwnProperty (propertyName):指定されたプロパティが現在のオブジェクトインスタンスに存在するかどうかを確認します;
-
isPrototypeOf (object):渡されたオブジェクトが渡されたオブジェクトのプロトタイプであるかどうかを確認します;
-
propertyIsEnumerable();toLocaleString();
-
toString ():オブジェクトの文字列表現を返します;
-
valueOf ():オブジェクトの文字列、数値、またはブール値の表現を返します;
3.5 演算子#
- 文字列を比較する際、実際には 2 つの文字列の対応する位置の各文字の文字コード値を比較しています。
"23" < "3" // true
-
数値と文字列を比較する際、文字列は数値に変換され、その後数値として別の数値と比較されます;数値に変換できない場合は NaN に変換されます。
-
どんなオペランドも NaN と比較すると、結果は常に false です。
NaN == NaN // false
NaN === NaN // false
NaN > NaN // false
NaN < NaN // false
- 等しい(==)と厳密に等しい(===):厳密に等しいは、2 つのオペランドが変換されずに等しい場合にのみ true を返します。
"55" == 55 // true
"55" === 55 // false
- 条件演算子
variable = boolean_expression ? true_value : false_value;
3.6 文#
- ECMAScript にはブロックスコープが存在しないため、ループ内で定義された変数は外部からもアクセス可能です:
for (var i = 0; i < 10; i++) {
var j = 1;
}
console.log(i, j); // 10 1
- for-in 文はオブジェクトのプロパティを列挙するために使用できます。
for (property in expression) {
...
}
- break と continue 文は label 文と組み合わせて使用されます:これは主にループのネストで発生します。
var num = 0;
outermost:
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i == 5 && j ==5) {
break outermost;
}
num++;
}
}
console.log(num); // 55
3.7 関数#
- 関数の引数:引数は内部で配列として表され、関数が受け取るのは常にこの配列であり、配列にどの関数が含まれているかは関係ありません;arguments オブジェクトを通じてこの引数配列にアクセスします;命名された引数は便利ですが必須ではありません;arguments オブジェクトの値は対応する命名引数のメモリ空間とは独立していますが、それらの値は同期します。
function example(name, age) {
console.log('arguments:', arguments);
console.log('name:', name, 'age:', age);
name = 'DIYgod';
console.log(arguments[0]);
}
example('Anotherhome', '556', 'www.anotherhome.net');
// arguments: ["Anotherhome", "556", "www.anotherhome.net"]
// name: Anotherhome age: 556
// DIYgod
第 4 章 変数、スコープ、メモリの問題#
4.1 基本型と参照型の値#
-
オブジェクトを操作する際、実際にはオブジェクトの参照を操作しており、実際のオブジェクトを操作しているわけではありません。
-
変数から別の変数に基本型の値をコピーする際、その値のコピーが作成されます;変数から別の変数に参照型の値をコピーする際、ヒープに保存されているオブジェクトへのポインタがコピーされ、コピー後の 2 つの変数は同じオブジェクトを指します。
var o1 = {};
var o2 = o1;
o1.name = 'DIYgod';
console.log(o2.name); // DIYgod
var n1 = 1;
var n2 = n1;
n1 = 2;
console.log(n2); // 1
- 引数の渡し方:引数は値としてのみ渡され、引数がオブジェクトの場合、関数内部でアクセスするのは同じオブジェクトです。
function setName(o) {
o.name = 'DIYgod';
o = {};
o.name = 'Anotherhome';
}
var p = {};
setName(p);
console.log(p.name); // DIYgod
- 値がどの基本型であるかを確認するには typeof 演算子を使用し、値がどの参照型であるかを確認するには instanceof 演算子を使用します。
4.2 実行環境とスコープ#
-
実行環境にはグローバル実行環境と関数実行環境があります;各実行環境には関連する変数オブジェクトがあります;新しい実行環境に入るたびに、変数と関数を検索するためのスコープチェーンが作成され、スコープチェーンの前端は現在実行中のコードが存在する変数環境であり、最後のオブジェクトはグローバル実行環境の変数オブジェクトです。
-
識別子の検索:スコープチェーンの前端から始めて、上に向かって逐次検索し、見つかった時点で検索結果が停止し、見つからなければグローバル環境の変数オブジェクトまで追跡します。
4.3 ガベージコレクション#
-
最も一般的なガベージコレクションの方法はマーク&スイープです:ガベージコレクタは実行時にメモリに保存されているすべての変数にマークを付け、その後環境内の変数や環境内の変数によって参照されている変数のマークを削除します。その後、まだマークが付いている変数は削除準備中の変数と見なされ、これらの変数にはアクセスできなくなります。
-
メモリ使用量の最適化:実行中のコードに必要なデータのみを保存します;データがもはや必要でなくなった場合、その値を null に設定して参照を解放するのが最善です —— 参照を解除します;参照を解除することは、その値を実行環境から切り離すことを目的としており、次回ガベージコレクタが実行されるときに回収できるようにします。
第 5 章 参照型#
5.1 Object 型#
- Object インスタンスを作成する:Object コンストラクタを使用;オブジェクトリテラル。
// new演算子を使用する方法
var o1 = new Object();
o1.name = 'DIYgod';
o1.age = 20;
// オブジェクトリテラル表記法
var o1 = {
name: 'DIYgod',
age: 20
}
- オブジェクトプロパティへのアクセス:ドット表記法;ブラケット表記法。ドット表記法の使用を推奨します。
// ドット表記法
console.log(o.name);
// ブラケット表記法
console.log(o['name']);
var n = 'name';
console.log(o[n]);
console.log(o['first name']);
5.2 Array 型#
- 配列を作成する:Array コンストラクタを使用;配列リテラル表記法を使用。
var a1 = new Array();
var a2 = new Array(20);
var a3 = new Array('red', 'blue', 'green');
var a4 = [];
var a5 = ['red', 'blue', 'green'];
- length を利用して末尾に新しい項目を追加します。
var a = ['a', 'b'];
a[a.length] = 'c';
-
配列を検出する:Array.isArray ()(2 つ以上のグローバル実行環境が存在する場合の instanceof 検出結果のエラーを解決します)。
-
スタックメソッドとキュー方法:push () は配列の末尾に項目を追加します;pop () は配列の末尾の項目を削除します;shift () は配列の最初の項目を削除します;unshift ();配列の先頭に項目を追加します。
-
再配置
-
reverse ():配列項目の順序を反転します。
-
sort ():デフォルトでは配列項目を文字列に変換して昇順に並べ替えます。比較関数を引数として受け取ることができます。
比較関数は 2 つの引数を受け取り、最初の引数が 2 番目の引数の前にある場合は負の数を返し、等しい場合は 0 を返し、2 番目の引数が最初の引数の前にある場合は負の数を返します。
var a = [0, 1, 15, 10, 5];
a.sort();
console.log(a) // [0, 1, 10, 15, 5]
function compare(value1, value2) {
return value1 - value2;
}
a.sort(compare);
console.log(a) // [0, 1, 5, 10, 15]
- 操作メソッド
- concat ():項目を追加します。
var a1 = ['red', 'green', 'blue'];
var a2 = a1.concat('yellow', ['black', 'brown']);
console.log(a2) // ["red", "green", "blue", "yellow", "black", "brown"]
- slice ():切り取ります。
var a = ["red", "green", "blue", "yellow", "black", "brown"];
console.log(a.slice(1), a.slice(1, 4)) // ["green", "blue", "yellow", "black", "brown"] ["green", "blue", "yellow"]
- splice ():削除、挿入、置換。
var a = ["red", "green", "blue", "yellow", "black", "brown"];
console.log(a.splice(2, 1), a); // 削除項目; ["blue"] ["red", "green", "yellow", "black", "brown"]
console.log(a.splice(1, 0, 'yellow', 'orange'), a); // 挿入項目; [] ["red", "yellow", "orange", "green", "yellow", "black", "brown"]
console.log(a.splice(1, 1, 'red', 'purple'), a); // 置換項目; ["yellow"] ["red", "red", "purple", "orange", "green", "yellow", "black", "brown"]
- 位置メソッド:indexOf () lastIndexOf () は 2 つの引数を受け取ります:検索する項目と(オプション)検索開始位置のインデックス;indexOf () は前から後ろに検索し、lastIndexOf () は後ろから前に検索します;検索する項目の位置を返し、見つからなければ - 1 を返します。
var a = ["red", "purple", "orange", "green", "red", "yellow", "black", "brown"];
console.log(a.indexOf('red')); // 0
console.log(a.lastIndexOf('red')); // 4
console.log(a.indexOf('red', 1)); // 4
console.log(a.lastIndexOf('red', 1)); // 0
- 繰り返しメソッド:every () some () filter () map () forEach ()。
var a = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var everyResult = a.every(function (item, index, array) {
return (item > 2);
});
console.log(everyResult); // false
var someResult = a.some(function (item, index, array) {
return (item > 2);
});
console.log(someResult); // true
var filterResult = a.filter(function (item, index, array) {
return (item > 2);
});
console.log(filterResult); // [3, 4, 5, 4, 3]
var mapResult = a.map(function (item, index, array) {
return (item * 2);
});
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
var forEachResult = a.forEach(function (item, index, array) {
console.log(item);
});
console.log(forEachResult); // undefined
- まとめメソッド
var a = [1, 2, 3, 2, 1];
var sum1 = a.reduce(function (prev, cur, index, array) {
console.log(index); // 1 2 3 4
return prev + cur;
});
console.log(sum1); // 9
var sum2 = a.reduceRight(function (prev, cur, index, array) {
console.log(index); // 3 2 1 0
return prev + cur;
});
console.log(sum2); // 9
5.3 Date 型#
- 日付オブジェクトを作成する:月は 0 から始まります(一月は 0、二月は 1...)。
var d1 = new Date();
var d2 = new Date(2015, 2, 5, 17, 55, 55); // 2015年3月5日午後5時55分55秒
- 呼び出し時の日時とミリ秒数を取得し、コードを分析するために使用できます。
var start = Date.now();
doSomething();
var stop = Date.now();
var result = stop - start;
- 日付フォーマットメソッド:local は地域特有の形式で表示されます。
var d2 = new Date(2015, 2, 5, 17, 55, 55);
d2.toString(); // "Thu Mar 05 2015 17:55:55 GMT+0800 (CST)"
d2.toDateString(); // "Thu Mar 05 2015"
d2.toTimeString(); // "17:55:55 GMT+0800 (CST)"
d2.toLocaleString(); // "2015/3/5 午後5:55:55"
d2.toLocaleDateString(); // "2015/3/5"
d2.toLocaleTimeString(); // "午後5:55:55"
5.4 RegExp 型#
- 正規表現を作成する:
pattern 部分は正規表現
flags、フラグは正規表現の動作を示します:g グローバルモード;i 大文字と小文字を区別しない;m 複数行モード
var exp1 = / pattern / flags
var exp2 = new RegExp('pattern', 'flags');
- インスタンスメソッド:
- exec ():最初の一致情報の配列を返します。配列の最初の項目は全体のパターンに一致する文字列で、他の項目はパターン内のキャプチャグループに一致する文字列です;index と input という 2 つの追加プロパティも含まれます。
var text = "I'm DIYgod, and this is Anotherhome";
var pattern = /and( this( is)?)?/gi;
var matches = pattern.exec(text);
console.log(matches.index); // 12
console.log(matches.input); // I'm DIYgod, and this is Anotherhome
console.log(matches[0]); // and this is
console.log(matches[1]); // this is
console.log(matches[2]); // is
- test ():パターンがこの引数と一致する場合は true を返し、そうでない場合は false を返します。
var text = "I'm DIYgod, and this is Anotherhome";
var pattern = /DIYgod/;
var matches = pattern.test(text);
console.log(matches); // true
- RegExp コンストラクタには、スコープ内のすべての正規表現に適用されるいくつかのプロパティが含まれ、最近の正規表現操作に関する情報を記録します。
5.5 Function 型#
- 関数を定義する。関数は実際には Function 型のインスタンスであり、したがって関数もオブジェクトです。
// 関数宣言構文を使用
function f1 (n1, n2) {
return n1 + n2;
}
// 関数式を使用
var f2 = function (n1, n2) {
return n1 + n2;
};
// コンストラクタを使用することは推奨されません
var f3 = new Function('n1', 'n2', 'return n1 + n2');
- 関数名は関数オブジェクトへのポインタです。
function f1 (n1, n2) {
return n1 + n2;
}
var f2 = f1;
f1 = null;
console.log(f2(1, 1)); // 2
-
ECMAScript には関数のオーバーロードはありません。
-
関数宣言と関数式の違い:インタプリタは関数宣言を最初に読み込み、コードを実行する前に利用可能にします(関数宣言のホイスティング);関数式はインタプリタがその行に到達するまで実際に解釈されません。
console.log(f1(1, 1)); // 2
function f1 (n1, n2) {
return n1 + n2;
}
console.log(f2(1, 1)); // Uncaught TypeError: f2 is not a function
var f2 = function(n1, n2) {
return n1 + n2;
}
- 関数内部のプロパティ
- 関数の arguments オブジェクトの callee プロパティ:この arguments オブジェクトを持つ関数を指すポインタです。再帰時に関数と関数名の結合を減らすことができます。
// 明らかに2番目の書き方の方が良い
function factorial1 (num) {
if (num <= 1) {
return 1;
}
else {
return num * factorial1(num - 1);
}
}
function factorial2 (num) {
if (num <= 1) {
return 1;
}
else {
return num * arguments.callee(num - 1);
}
}
- caller プロパティ:現在の関数の関数の参照を保持します。
function outer() {
inner();
}
function inner() {
console.log(arguments.callee.caller); // function outer()...
}
outer();
- 関数のプロパティとメソッド
- length プロパティ:関数が受け取ることを希望する命名引数の数を示します。
function f (n1, n2) {
return n1 + n2;
}
console.log(f.length); // 2
- apply () call ():関数の this オブジェクトの値を変更するために使用されます。
window.color = 'red';
var o = {
color: 'blue'
};
function sayColor (n1, n2) {
console.log(this.color);
return n1 + n2;
}
sayColor(1, 1); // red
o.sayColor = sayColor;
o.sayColor(); // blue
// callとapplyを使用すると、オブジェクトとメソッドの結合関係を解消できます
sayColor.call(window, 1, 1); // red
sayColor.call(o, 1, 1); // blue
sayColor.apply(window, [1, 1]); // red
sayColor.apply(o, [1, 1]); // blue
5.6 基本ラッパー型#
Boolean 型、Number 型、String 型
一時的にスキップします
5.7 単体内蔵オブジェクト#
Global オブジェクト、Math オブジェクト
一時的にスキップします
第 6 章 オブジェクト指向プログラミング#
6.1 オブジェクトの理解#
- 2 種類のプロパティ:データプロパティとアクセサプロパティ。特性:プロパティのさまざまな特性を記述するもので、JavaScript エンジンが使用するためのものであり、直接アクセスすることはできません。
- データプロパティには 4 つの特性があります:
-
[[Configurable]]:delete を通じてプロパティを削除して再定義できるか、プロパティの特性を変更できるか、プロパティをアクセサプロパティに変更できるかを示します。
-
[[Enumerable]]:for-in ループを通じてプロパティを返すことができるかを示します。
-
[[Writeable]]:プロパティの値を変更できるかを示します。
-
[[Value]]:このプロパティのデータ値を含みます。
- アクセサプロパティには 4 つの特性があります:
-
[[Configurable]]:delete を通じてプロパティを削除して再定義できるか、プロパティの特性を変更できるか、プロパティをデータプロパティに変更できるかを示します。
-
[[Enumerable]]:for-in ループを通じてプロパティを返すことができるかを示します。
-
[[Get]]:プロパティを読み取るときに呼び出される関数。
-
[[Set]]:プロパティを書き込むときに呼び出される関数。
- 特性の定義と読み取り:Object.defineProperty () Object.defineProperties () Object.getOwnPropertyDescriptor ()
6.2 オブジェクトの作成#
- ファクトリーパターン:複数の類似オブジェクトを作成する問題を解決しましたが、オブジェクトの識別問題は解決されませんでした。
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
console.log(this.name);
}
return o;
}
var p1 = createPerson('DIYgod', 20, 'Software Engineer');
var p2 = createPerson('Anotherhome', 2, 'Website');
- コンストラクターパターン。(コンストラクタは大文字で始まるべきです)
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
console.log(this.name);
}
}
var p1 = new Person('DIYgod', 20, 'Software Engineer');
var p2 = new Person('Anotherhome', 2, 'Website');
// p1とp2はそれぞれPersonの異なるインスタンスを保持しており、これらのオブジェクトにはそれぞれconstructorプロパティがあり、そのプロパティはPersonを指します
console.log(p1.constructor); // function Person(name, age, job) {...
console.log(p1 instanceof Object); // true
console.log(p1 instanceof Person); // true
この方法は 4 つのステップを経ます:
-
新しいオブジェクトを作成します。
-
コンストラクタのスコープを新しいオブジェクトに割り当てます(this はこの新しいオブジェクトを指します)。
-
コンストラクタ内のコードを実行します(新しいオブジェクトにプロパティを追加します)。
-
新しいオブジェクトを返します。
コンストラクタの問題:各メソッドは各インスタンスで再作成される必要があります。
console.log(p1.sayName === p2.sayName); // false
- プロトタイプパターン:各関数には prototype プロパティがあり、このプロパティはオブジェクト(関数のプロトタイプオブジェクト)を指し、このオブジェクトにはそのタイプのすべてのインスタンスが共有できるプロパティとメソッドが含まれています。
// コンストラクターパターンとプロトタイプパターンを組み合わせて使用
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayName = function () {
console.log(this.name);
}
var p1 = new Person('DIYgod', 20, 'Software Engineer');
var p2 = new Person('Anotherhome', 2, 'Website');
console.log(p1.sayName === p2.sayName); // true
- プロトタイプオブジェクトを理解する:
-
新しい関数を作成すると、特定のルールに基づいてその関数に prototype プロパティが作成され、プロトタイプオブジェクトを指します。
-
デフォルトでは、すべてのプロトタイプオブジェクトには constructor プロパティがあり、prototype プロパティがある関数を指します。
-
コンストラクタを呼び出して新しいインスタンスを作成すると、インスタンスには__proto__プロパティがあり、コンストラクタのプロトタイプオブジェクトを指します。このポインタは [[Prototype]] と呼ばれ、デフォルトのプロトタイプは Object を指します。
-
インスタンスとコンストラクタには直接の関係はありません。
-
プロパティの読み取り:最初にオブジェクトインスタンスから検索を開始し、見つからなければプロトタイプオブジェクトを検索します。
-
isPrototype () を使用して、コンストラクタとインスタンスの間に関係があるかどうかを検出します。
-
hasOwnProperty () を使用して、プロパティがインスタンスに存在するかプロトタイプに存在するかを検出します。
- プロトタイプと in 演算子
// in演算子は、オブジェクトを通じてプロパティにアクセスできる場合にtrueを返します
console.log('name' in p1); // true
// プロパティを列挙します
for (var prop in p1) {
console.log(prop); // name age job sayName
}
- オブジェクトリテラルを使用してプロトタイプオブジェクトを再定義します
function Person() {
}
Person.prototype = {
constructor: Person, // ここでprototypeを再定義し、デフォルトのconstructorプロパティを持たなくなります
name: 'DIYgod',
age: 20
};
- 動的プロトタイプパターン、寄生コンストラクターパターン、妥当なコンストラクターパターン
6.3 継承#
- JavaScript で最も一般的な継承:組み合わせ継承。プロトタイプチェーンとコンストラクタの利点を融合させています。
function SuperType(name) {
this.name = name;
this.color = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
}
function SubType(name, age) {
SuperType.call(this, name); // コンストラクタを借用
this.age = age;
}
SubType.prototype = new SuperType(); // プロトタイプチェーン
SubType.prototype.constructor = SubType; // construcotrは前の行で再定義されました
SubType.prototype.sayAge = function () {
console.log(this.age);
}
var instance = new SubType('DIYgod', 20);
instance.sayName(); // DIYgod
instance.sayAge(); // 20
- プロトタイプとインスタンスの関係を確認します。前の例を続けます:
console.log(instance instanceof SuperType); // true
console.log(SuperType.prototype.isPrototypeOf(instance)); // true
- プロトタイプ式継承、寄生式継承、寄生組み合わせ式継承
第 7 章 関数式#
7.1 再帰#
7.2 クロージャ#
-
クロージャは、別の関数のスコープ内の変数にアクセスする権限を持つ関数です。
-
(スコープチェーンは 4.2 を参照)外部関数内で定義された内部関数は、外部関数のアクティブオブジェクトをそのスコープに追加します;外部関数が完了すると、そのアクティブオブジェクトは破棄されません。なぜなら、内部関数のスコープチェーンはまだこのアクティブオブジェクトを参照しているからです;外部関数が完了した後も、内部関数は定義されたすべての変数にアクセスできます。
function outer () {
var name = 'DIYgod';
return function () {
console.log(name);
}
}
var inner = outer();
inner(); // DIYgod
inner = null; // outer内部の匿名関数への参照を解除し、メモリを解放します
- クロージャは、関数内の任意の変数の最後の値を取得することができます。
function createFunction () {
var result = [];
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
}
}
return result;
}
console.log(createFunction()[0]()); // 10
console.log(createFunction()[1]()); // 10
// 返されるのは同じ変数iです
- 匿名関数の this は通常 window を指します。
var name = 'The Window';
var object = {
name: 'My Object',
getNameFunc: function () {
return function () {
return this.name;
}
}
}
console.log(object.getNameFunc()()); // The Window
7.3 ブロックスコープの模倣#
- 匿名関数を使用してブロックスコープを模倣します:最初の括弧の役割は関数宣言を関数式に変換することです(関数宣言は後に括弧を付けて呼び出すことはできません)、2 番目の括弧はこの関数を呼び出します。
(function () {
var i = 9;
console.log(i); // 9
})();
console.log(i); // Uncaught ReferenceError: i is not defined
7.4 静的オブジェクト#
-
関数内で定義された変数はすべてプライベート変数と見なすことができます。
-
プライベート変数とプライベート関数にアクセスする権限を持つ公有メソッドは特権メソッドと呼ばれます。
function MyObject() {
// プライベート変数とプライベート関数
var privateVariable = 'DIYgod';
function privateFunction() {
console.log('lalala');
}
// 特権メソッド
this.publicMethod = function () {
console.log(privateVariable);
privateFunction();
};
}
var o = new MyObject();
o.publicMethod(); // DIYgod lalala
o.privateFunction(); // Uncaught TypeError: o.privateFunction is not a function
...
第 13 章 イベント#
13.1 イベントフロー#
-
イベントバブリング:イベントは最も具体的な要素から受信され、次第に不具体的なノードに向かって伝播します;IE9、FireFox、Chrome、Safari はイベントを window オブジェクトまでバブリングさせます。
-
イベントキャプチャ:古いバージョンのブラウザがサポートしていないため、イベントキャプチャはほとんど使用されません。
-
「DOM2 レベルイベント」で規定されたイベントフローには、3 つの段階があります:イベントキャプチャ段階、ターゲット段階、イベントバブリング段階。
13.2 イベントハンドラ#
- HTML イベントハンドラ:スコープを拡張し、関数内部で document やその要素自体のメンバーにアクセスすることができます。例:
<input type="button" value="Click Me" onclick="alert(value)">
フォーム入力要素の場合、スコープにはフォーム要素へのアクセスも含まれます。例:
<form method="post">
<input type="text" name="username" value="">
<input type="button" value="Echo username" onclick="alert(username.value)">
</form>
欠点:①関数が解析される前にイベントがトリガーされるとエラーが発生する遅延の問題 ②異なるブラウザでのハンドラのスコープチェーンの違い ③HTML と JavaScript コードの密結合を引き起こします。
- DOM0 レベルイベントハンドラ
// イベントハンドラをバインドする
var btn = document.getElementById('myButton');
btn.onclick = function () {
console.log(this.id); // myButton
}
// イベントハンドラを削除する
btn.onclick = null;
この方法で追加されたイベントハンドラは、イベントフローのバブリング段階で処理されます。
- DOM2 レベルイベントハンドラ
addEventListener () と removeEventListener ()
3 つのパラメータ:処理するイベント名、イベントハンドラとしての関数、キャプチャ段階で関数を呼び出すか(true)、バブリング段階で呼び出すか(false、デフォルト)
利点は、複数のイベントハンドラを追加できることです。addEventListener で追加されたイベントハンドラは removeEventListener でのみ削除でき、匿名関数は削除できません。
- IE イベントハンドラ
attachEvent () と detachEvent ()
var btn = document.getElementById('myButton');
btn.attachEvent('onclick', function () {
console.log(this === window); // myButton
});
この方法で追加されたイベントハンドラは、イベントフローのバブリング段階で処理されます。
13.3 イベントオブジェクト#
-
DOM 上の特定のイベントがトリガーされると、イベントオブジェクト event が生成され、このオブジェクトにはイベントに関連するすべての情報が含まれます。イベントハンドラが実行されている間のみ、event オブジェクトは存在し、イベントハンドラが実行を完了すると、event オブジェクトは破棄されます。
-
プロパティ / メソッド:
currentTarget:イベントを処理している要素
target:イベントのターゲット
type:イベントの種類
cancelable:特定のイベントのデフォルトの動作を防ぐことができるかどうか
preventDefault ():特定のイベントのデフォルトの動作を防ぎます
stopPropagation ():イベントが DOM 階層内で伝播するのを停止します。つまり、さらなるイベントキャプチャまたはバブリングをキャンセルします
eventPhase:イベントがイベントフローのどの段階にあるか。キャプチャ段階は 1、ターゲットオブジェクトは 2、バブリング段階は 3 です。
13.4 イベントタイプ#
- UI イベント、フォーカスイベント、マウスイベント、ホイールイベント、テキストイベント、キーボードイベント、合成イベント、変化イベント。
...
第 21 章 Ajax と Comet#
21.1 XMLHttpRequest オブジェクト#
- 使用法
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
console.log(xhr.responseText);
}
else {
console.log('Request was unsuccessful: ' + xhr.status);
}
}
};
xhr.open('get', 'example.php', true);
xhr.send(null);
-
XHR オブジェクトを作成する:new XMLHttpRequest ();
-
open ():送信のためのリクエストを開始します;3 つのパラメータ:リクエストタイプ、リクエスト URL、リクエストを非同期で送信するかどうか(同期はサーバーの応答を待ってから続行する必要があります);リクエストは実際には送信されません。
-
send ():リクエストを送信します;1 つのパラメータ:送信するデータ;データを送信する必要がない場合は null を渡す必要があります。
-
XHR オブジェクトのプロパティ:
-
responseText:返されたテキスト
-
status:応答の HTTP ステータス。
- HTTP ステータスコード:
-
2xx 成功
-
3xx リダイレクト、304 Not Modified はリクエストされたリソースが変更されていないことを示し、ブラウザのキャッシュされたバージョンを直接使用できます。302 Found はリクエストされたリソースが現在一時的に異なる URI から応答していることを示します。
-
4xx クライアントエラー、403 Forbidden、404 Not Found
-
5xx サーバーエラー、500 Internal Server Error、503 Service Unavailable。
- XHR の readyState プロパティ:
-
0:未初期化
-
1:開始、open () が呼び出されました
-
2:送信、send () が呼び出されました
-
3:部分的な応答データが受信されました
-
4:すべての応答データが受信されました
- readystatechange イベント:readyState プロパティの値が 1 つの値から別の値に変わると、readystatechange イベントがトリガーされます。
21.4 クロスオリジンリソースシェアリング#
-
CORS:カスタム HTTP ヘッダーを使用してブラウザとサーバー間で通信し、リクエストまたは応答が成功すべきか失敗すべきかを決定します。IE では XDR オブジェクトを使用して実現し、他のブラウザでは XHR オブジェクトがネイティブにサポートされています。
-
画像 Ping:GET リクエストのみを送信できます;サーバーの応答テキストにアクセスできません。
var img = new Image();
img.onload = img.onerror = function () {
console.log('Done!');
};
img.src = 'http://api.hitokoto.us/rand?encode=jsc';
- JSONP:2 つの部分から構成されます。コールバック関数とデータ。
function myCallBack (data) {
console.log(data.hitokoto); // 普通のあなたのように奇跡を引き起こしてください-
}
var script = document.createElement('script');
script.src = 'http://api.hitokoto.us/rand?encode=jsc&fun=myCallBack'; // JSON内の関数呼び出しを含むものを返し、myCallBack関数を呼び出します:myCallBack({"hitokoto":"...","author":"...",....});
document.body.insertBefore(script, document.body.firstChild);
欠点:安全性が信頼できない;リクエストの失敗を判断するのが難しい。
続く...