JavaScript_javascript スキルの言語機能の分析に関する簡単な説明
はじめに
JavaScript では、スコープ、コンテキスト、クロージャー、関数などが最高のものです。初心者の JSers にとっては、上級レベルの必需品です。フロントエンドのシージエンジニアは、落ち着いてこれらの本質を理解することによってのみ、エレガントなコードを書くことができます。
この記事は、忘れがちな重要な知識を要約することを目的としており、基本的な概念については説明しません。基本的な知識がよくわからない場合は、「JavaScript の決定版ガイド」を読んでください~
言語特徴関数式
まずコード スニペットを見てください:
[javascript] view plaincopyprint?
var f = function foo(){
return typeof foo; // foo は内部スコープ内で有効です
};
// foo は外部で使用されると非表示になります
typeof foo; // " "
f(); // "function"
var f = function foo(){
return typeof foo; // foo は内部スコープ
};
// foo 外部で使用する場合は非表示
typeof foo // "unknown"
f() // "function"
ここで言いたいのは、関数式内の foo は関数内でのみ参照でき、関数外では参照できないということです。
json
多くの JavaScript 開発者は、JavaScript オブジェクト リテラル (JSON オブジェクト) を誤って呼んでいます。 JSON はデータ交換形式を記述するように設計されており、JavaScript のサブセットである独自の構文も備えています。
{ “prop”: “val” } このような宣言は、使用されるコンテキストに応じて、JavaScript オブジェクト リテラルまたは JSON 文字列の場合があります。文字列コンテキスト (一重引用符または二重引用符で囲まれるか、テキスト ファイルから読み取られる) で使用される場合、それは JSON 文字列です。オブジェクト リテラル コンテキストで使用される場合、それはオブジェクト リテラルです。
[javascript] view plaincopyprint?
// これは JSON 文字列です
var foo = '{ "prop": "val" }'
// これはオブジェクト リテラルです
var bar = { "prop": "val" } ;
// これは JSON 文字列です
var foo = '{ "prop": "val" }';
// これはオブジェクト リテラルです
var bar = { "prop": "val" };
もう 1 つ知っておくべきことは、JSON.parse は JSON 文字列をオブジェクトに逆シリアル化するために使用され、JSON.stringify はオブジェクトを JSON 文字列にシリアル化するために使用されるということです。古いバージョンのブラウザはこのオブジェクトをサポートしていませんが、json2.js を通じて同じ機能を実現できます。
プロトタイプ
function Animal (){
/ / .. .
}
function cat (){
// ...
}
cat.prototype = new Animal();//このメソッドは、コンストラクタ。
cat.prototype = Animal.prototype;//このメソッドはコンストラクターを継承しません。
//もう 1 つ注意すべき重要な点は、独自のプロトタイプ チェーンを保守する必要があるということです。初心者はこれを常に忘れてしまいます。
cat.prototype.constructor = cat;
(新しいオブジェクトを割り当てることによって) 関数のプロトタイプ プロパティを完全に変更すると、作成するオブジェクトにはコンストラクター プロパティが含まれないため、元のコンストラクターへの参照が失われます。
function A() {}
A.prototype = {
x: 10
};
var a = new A();
alert(a.x) // 10
alert(a.constructor === A) ); // false!
MDN のコンストラクターの説明を見てみましょう。 プロトタイプ: インスタンスのプロトタイプを作成したオブジェクト関数への参照を返します。 したがって、関数へのプロトタイプ参照は手動で復元する必要があります。
function A() {}
A.prototype = {
コンストラクター: A,
x: 10
};
var a = new A();
alert(a.x); // 10
alert( a.constructor === A) // true
ただし、プロトタイプ属性を送信しても、すでに作成されているオブジェクトのプロトタイプには影響しません (コンストラクターのプロトタイプ属性が変更された場合にのみ影響を受けます)。つまり、新しく作成されたオブジェクトのみが新しいプロトタイプを持ちます。すでに作成されたオブジェクトには、元の古いプロトタイプへの参照が引き続き残ります (このプロトタイプは変更できなくなります)。
function A() {}
A.prototype .x = 10;
var a = new A();
alert(a.x); // 10
A.prototype = {
コンストラクター: A,
x: 20
y: 30
};
//オブジェクト a は、暗黙的な [[Prototype]] 参照
alert(a.x) を通じて原油のプロトタイプから取得された値です。 🎜>alert (a.y) // unknown
var b = new A();
// ただし、新しいオブジェクトは新しいプロトタイプから取得された値です
alert(b.x) // 20alert(b.y) // 30
変数オブジェクト 関数実行コンテキストでは、VO(変数オブジェクト)に直接アクセスすることはできません。このとき、活性化オブジェクト(活性化オブジェクト)がVOの役割を果たします。 アクティブ オブジェクトは、関数コンテキストに入るときに作成され、関数の argument 属性を通じて初期化されます。 argument 属性の値は Arguments オブジェクトです:
alter(foo.length); // 3
// 実際に渡されるパラメータの数 (x, のみ) y)
alter(arguments.length); // 2
// パラメータの呼び出し先は関数自体です
alter(arguments.callee === foo); // true
}
•すべての関数宣言 (FunctionDeclaration、FD);
•すべての変数宣言 (var、VariableDeclaration)
もう 1 つの典型的な例:
alert(x); // 10
x = 20;
function x() {};
alert(x); 🎜>
仕様によれば、コンテキストに入るときに関数宣言が入力されます。また、コンテキストに入るときに変数宣言「x」があり、その後、上で述べたように、変数宣言は関数宣言とフォームの後に続きます。この入力コンテキスト段階では、変数宣言は、VO にすでに存在する同じ名前の関数宣言または仮パラメータ宣言を妨げません。単純な属性と比較して、変数には {DontDelete} という属性があります。この属性の意味は、変数属性を delete 演算子を使用して直接削除できないことです。
コードをコピー
var b = 20;
alert(window.b) ; // 20
alert(delete b); // false
alert(window.b); // 20 のままです。 b は変数であり、プロパティではありません!
var a = 10; // グローバル コンテキストの変数
(function () {
var b = 20; // 関数コンテキストのローカル変数
} )( );
alert(a); // 10
alert(b); // グローバル変数 "b" が宣言されていません。
This 関数コンテキストでは、this は呼び出し元によって提供され、関数の呼び出し方法によって決定されます。呼び出し括弧 () の左側が参照型の値である場合、これは参照型値の基本オブジェクトに設定されます。それ以外の場合 (参照型とは異なるその他のプロパティ)、この値は null になります。 。ただし、this の値が null である実際の状況はありません。this の値が null の場合、その値は暗黙的にグローバル オブジェクトに変換されるからです。
コードをコピー
(function () {
alert(this); // null => global
})();
この例では、関数オブジェクトはありますが、参照型オブジェクトはありません (識別子でもプロパティ アクセサーでもありません)。したがって、 this 値は最終的にグローバル オブジェクトに設定されます。
var foo = {
bar: function () {
alert(this);
}
};
foo.bar(); // 参照、OK => foo
(foo.bar); // 参照、OK => foo
(foo.bar = foo.bar)(); // global
(false || foo.bar)(); // global
(foo.bar) , foo .bar)() // グローバル
問題は、次の 3 つの呼び出しでは、特定の操作を適用した後、呼び出し括弧の左側の値が参照型ではなくなることです。
•最初の例は明らかです - 明らかな参照型です。結果として、これが基本オブジェクト、つまり foo になります。
• 2 番目の例では、グループ演算子は適用されません。GetValue など、参照型からオブジェクトの実際の値を取得する上記のメソッドを考えてください。同様に、グループ操作の戻りでも参照型を取得します。これが、 this 値がベース オブジェクト (foo) に再度設定される理由です。
•3 番目の例では、グループ演算子とは異なり、代入演算子は GetValue メソッドを呼び出します。返される結果は関数オブジェクト (参照型ではありません) です。つまり、これは null に設定され、結果はグローバル オブジェクトになります。
• 4 番目と 5 番目も同様です。コンマ演算子と論理演算子 (OR) が GetValue メソッドを呼び出し、それに応じて参照が失われ、関数が取得されます。そして、再度グローバルに設定します。
ご存知のとおり、ローカル変数、内部関数、仮パラメータは、指定された関数のアクティベーション オブジェクトに格納されます。
function foo() {
function bar() {
alter(this); // グローバル
}
bar() // AO.bar()
}
アクティブなオブジェクトは常に this として返され、値は null です (つまり、疑似コードの AO.bar() は null.bar() と同等です)。ここで、これをグローバル オブジェクトに設定して、上で説明した例に戻ります。
スコープチェーン
関数コンストラクターを通じて作成された関数のスコープ属性は、常に唯一のグローバル オブジェクトです。
重要な例外の 1 つは、関数コンストラクターを介して作成された関数に関するものです。
var x = 10;
function foo() {
var y = 20;
function barFD() { // 関数宣言
alert(x);
alert(y);
}
var barFn = Function(' アラート(x); アラート(y);');
barFD() // 10, 20
barFn(); // 10, "y" が定義されていません
}
foo ();
また:
var x = 10, y = 10;
with ({x: 20}) {
var x = 30, y = 30;
//x = 30 ここでは x = 20 をカバーします。 🎜 > アラート(y); // 30
}
アラート(x) // 10
アラート(y);
コンテキストを入力するとどうなりますか?識別子「x」と「y」が変数オブジェクトに追加されました。さらに、コードの実行フェーズ中に次の変更を加えます:
•x = 10, y = 10;
•オブジェクト {x:20} がスコープの先頭に追加されます;
•with 内で var 宣言が検出されますが、もちろん何もありませんコンテキストに入るときに、すべての変数が解析されて追加されているため、 が作成されます。
• 2 番目のステップでは、変数 "x" のみが変更され、実際にはオブジェクト内の "x" が解析されて追加されます。スコープチェーンの先頭、「x」は 20 で 30 になります;
• 変数オブジェクト「y」も解析された後、値が 10 から 30 に変わります;
•さらに、with ステートメントが完了すると、その特定のオブジェクトがスコープ チェーンから削除されます (変更された変数 "x" - 30 もそのオブジェクトから削除されます)。つまり、スコープ チェーンの構造が状態に復元されます。 withが強化される前。
•最後の 2 つのアラートでは、現在の変数オブジェクトの "x" は同じままですが、"y" の値は 30 に等しくなりますが、これは with ステートメントの実行中に変更されました。
関数
括弧に関する質問
質問を見てみましょう: 「関数を作成した直後に呼び出す場合、なぜ関数を括弧で囲む必要があるのですか?」 』の答えは、表現文の制限はこうです。
標準によれば、式ステートメントはコード ブロックと区別することが難しいため、中括弧 { で始めることはできません。同様に、関数宣言と区別することが難しいため、関数キーワードで始めることもできません。つまり、作成直後にすぐに実行する関数を定義する場合は、次のように呼び出します:
function () {
.. .
}();
// 名前があっても
function foo() {
...
}();
上記 2 つの定義では関数宣言を使用しましたが、インタープリターは解釈時にエラーを報告しますが、多くの理由が考えられます。これがグローバル コード (つまり、プログラム レベル) で定義されている場合、関数キーワードで始まるため、インタープリターはそれを関数宣言として扱います。最初の例では、関数宣言に名前がないため、SyntaxError が発生します。 (関数宣言には名前が必要であると前述しました)。 2 番目の例では、foo という名前の関数宣言が正常に作成されていますが、それでも構文エラー、つまり式のないグループ化演算子エラーが発生します。これは実際には、関数呼び出しで使用される括弧ではなく、関数宣言後のグループ化演算子です。したがって、次のコードを宣言するとします:
// "foo" は関数宣言です、入力後 Create
alert(foo); // Function
function foo(x) {
alter(x);
}(1); // これは単なるグループ化演算子です。関数呼び出し!
foo(10); // これは実際の関数呼び出しであり、結果は 10
式を作成する最も簡単な方法は、グループ化演算子の括弧を使用することです。そのため、インタープリタがそれを解釈するときにあいまいさがなくなります。この関数はコード実行フェーズ中に作成され、すぐに実行され、その後自動的に破棄されます (参照がない場合)
(function foo(x) {
alert(x);
})(1); // これはグループ化演算子ではなく呼び出しです
上記のコードは、式を括弧で囲み、(1) を通じて呼び出すものです。すぐに実行される次の関数の場合、関数を囲む括弧は必要ないことに注意してください。関数はすでに式の位置にあり、関数の実行フェーズで作成される必要がある FE を処理していることがパーサーに認識されているためです。 、関数が作成された直後に呼び出されます。
var foo = {
bar:関数 (x ) {
>
。
ご覧のとおり、foo.bar は文字列であり関数ではありません。この関数は条件パラメータに基づいてこのプロパティを初期化するためにのみ使用され、作成されてすぐに呼び出されます。
1. したがって、「括弧について」という質問に対する完全な答えは次のとおりです。
2. 関数が式の位置にない場合、グループ化演算子の括弧が必要です (つまり、手動で)。関数はFEに変換されます。
3. パーサーが FE を扱っていることを認識している場合は、括弧を使用する必要はありません。
自由変数:
function testFn() {
var localVar = 10 ;//innerFn 関数の場合、localVar は自由変数です。
function innerFn(innerParam) {
alert(innerParam localVar);
}
return innerFn;
}
クロージャーの静的スコープ:
var z = 10;
function foo() {
alert(z);
}
foo() // 10 – 静的スコープと動的スコープを使用する場合
(function () {
var z = 20;
foo(); // 10 - 静的スコープを使用、20 - 動的スコープを使用
})();
// foo がパラメーターとして使用される場合、同じ
(function (funArg) {
var z = 30;
funArg(); // 10 – 静的スコープ、30 – 動的スコープ
})(foo);
理論: スコープ チェーンのため、すべての関数はクロージャです (関数の種類に関係なく、匿名関数、FE、NFE、FD はすべてクロージャです)。実用的な観点から: 以下の関数はクロージャとみなされます: * 作成されたコンテキストが破棄された場合でも、依然として存在します (たとえば、内部関数が親関数から返される)
* コード内で自由変数
を参照します最後に:
ECMAScript は、プロトタイプベースの委任継承をサポートするオブジェクト指向言語です。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。
