ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript_javascript スキルの範囲を深く理解する

JavaScript_javascript スキルの範囲を深く理解する

WBOY
WBOYオリジナル
2016-05-16 16:39:48985ブラウズ

JavaScript を使用していると、誰もがこの男によく混乱します。 OOP 開発経験のあるほとんどの開発者にとって、これは現在のスコープ内の通常の要素を参照する識別子ですが、JavaScript では固定ではなく、実行環境の変化によって変化するため、奇妙に見えます。 JavaScript では、これは常にメソッドが呼び出されるオブジェクトを指します。

簡単な例を挙げてください:

コードをコピー コードは次のとおりです:

関数テスト(){
アラート(これ);
}
var obj=function(){
var name='testObj';
}
obj.objTest=テスト;
テスト();
obj.objTest();

このコードを HTML に入力してこのページを実行すると、最初に警告 [オブジェクト ウィンドウ] が表示され、次に 2 番目の警告が表示されます。

コードをコピーします コードは次のとおりです:

var obj=function(){
var name='testObj';
}

最初に test() メソッドを定義し、これを表示するためにメソッド内でalert() メソッドを呼び出しました。次に、obj 関数オブジェクトを定義し、それにプライベート フィールド名を追加し、静的メソッド objTest() を追加しました。が作成され、この関数は test() 関数を直接指します。

test() メソッドと obj.objTest() メソッドをそれぞれ呼び出します。最初の警告ボックスは Window オブジェクトを要求し、2 番目のプロンプトは定義した obj 関数のコードです。これは、テスト関数が 2 回実行されると this の値が異なることを示しています。

これは、関数を呼び出すオブジェクトが異なると、内部の this キーワードで参照されるオブジェクトも異なることを示しています。ここで、JavaScript はオブジェクトベースの言語であることに注意してください。変数または関数が <script></script> タグのルートで定義されることは、対応する属性またはメソッドをウィンドウに追加することと同じです。したがって、関数 test(){} コードを使用して関数を定義することは、実際には、新しい関数、つまり window.test() 関数をウィンドウ オブジェクトに追加することと同じになります。

実験してみましょう:

コードをコピーします コードは次のとおりです:

関数テスト(){
アラート(これ);
}
アラート(テスト===ウィンドウ.テスト);

警告ボックスのプロンプトは true になります。つまり、test() 関数を呼び出すと、window.test() を呼び出すのと同じになります。したがって、test() 関数を呼び出すとき、この関数を呼び出すオブジェクトは実際には window オブジェクトであり、this は window オブジェクトを参照するため、alert(this) を実行したときにポップアップ表示される警告ウィンドウの内容は [object Window] になります。 ]。 obj.objTest=test を設定します。これは、obj.objTest() を test() に指定するのと同じです。そのため、obj.objTest() 関数を呼び出すと、obj で test() 関数を呼び出すのと同じになります。 obj オブジェクトを参照すると、プロンプトが表示されるのは obj の関数であり、これが表示されるコードです。

上記の例は抽象的すぎて、どのような状況で使用できるのか想像できないかもしれません。そこで、要件を想定して、より実践的な例を作成してみましょう。

現在のページ内のすべてのハイパーリンクの色がクリック後に赤に変更されるとします。これは Javascript を使用して実装されます。一般的な考え方は、ページ内のすべての タグを取得し、すべての タグを調べて、イベントがトリガーされた後、その色の値を赤に設定することです。 。

サンプルコードは次のとおりです:

コードをコピー コードは次のとおりです:

//色を変更
関数changeColor(){
this.style.color='#f00';
}
//初期化し、すべての a タグのイベントを登録します
関数 init(){
varcustomLinks=document.getElementsByTagName('a');
for(カスタムリンク内の i){
//イベントリスナーを使用してイベントを登録することもできます
//IE、FF、その他のブラウザとの互換性のため、より多くのコードが必要になる場合がありますが、自分で記述することができます
CustomLinks[i].onclick=changeColor;
}
}
window.onload=init;

このコードを HTML ドキュメントに追加し、ドキュメントにいくつかのハイパーリンクを追加します。ハイパーリンクがクリックされると、ここで定義した changeColor() 関数の this キーワードがトリガーされます。関数では、現在のハイパーリンクを参照します。また、changeColor() 関数を直接呼び出すと、ブラウザはエラーを報告し、「エラー: 'this.style' が null か、オブジェクトではないか、または未定義です」などのエラーを表示します。

この記事を読んでいる皆さんは、これで Javascript の this キーワードについてある程度理解できるでしょうか?それともせっかちですか? (:P)

実際、この問題を本当に深く理解したい場合は、JavaScript のスコープとスコープ チェーンを深く理解する必要があります。

スコープとは、その名前が示すように、特定の属性またはメソッドがアクセス許可を持つコード空間を指します。簡単に言うと、コード内でその変数またはメソッドが適用される範囲です。ほとんどの OOP には、パブリック、プライベート、保護という 3 つの主要なスコープがあります。OOP の経験がある場合は、これら 3 つのスコープについて詳しく説明しません。ここで言いたいのは、JavaScript にはパブリック スコープが 1 つしかなく、JavaScript のスコープは関数内で維持されるため、これら 3 つのスコープ タイプは Javascript にとってほとんど意味がないということです。例:

コードをコピーします コードは次のとおりです:

var test1='グローバル変数';
関数 example(){
var test2='変数の例';
アラート(テスト1);
アラート(テスト2);
}
example();
アラート(テスト1);
アラート(テスト2);

前に説明したとおり、ここでの test1 変数は window の属性に相当するため、window スコープ全体で動作しますが、test2 は example() 関数内で宣言されているため、そのスコープは関数内で維持されます。 example() メソッドの場合、test2 ブラウザが関数の外で呼び出される場合、エラーが表示されます。 example() 内で test1 を呼び出すことに問題はありません。

これに基づいて、別の例を挙げてみましょう:

コードをコピー コードは次のとおりです:

var test='グローバル変数';
関数 example(){
var test='変数の例';
}
example();
アラート(テスト);

この例を実行するとどうなるでしょうか?はい。example() 関数内のテスト変数のスコープは内部のみに留まり、外部テスト変数には影響しないため、警告ボックスに「globle variable」というプロンプトが表示されます。 example() 内のテスト変数から var キーワードを削除したらどうなるでしょうか?自分で試してみることもできます。

これに関して言えば、スコープチェーンという別の概念が関係しています。スコープ チェーンは、変数の値を決定できるパスです。上記の例からわかるように、var キーワードはスコープ チェーンを維持するために使用されます。変数が var キーワードを使用して宣言されている場合、それはスコープ チェーンのエンドポイントと見なすことができます。同じ関数の仮パラメータの定義も同様の役割を果たします。

そういえば、この変な男についてもっと分かりやすくなりましたか?単純な解釈によれば、これは常に、それが配置されている関数を呼び出すオブジェクトを指します。スコープとスコープ チェーンに従って、これの本当の姿を明確に決定します。最後に、冒頭の例の簡単なバリエーションを示します:

コードをコピーします コードは次のとおりです:

関数テスト(){
アラート(これ);
}
var obj=function(){
var name='testObj';
}
obj.objTest=テスト;
obj.objTest2=function(){
テスト();
}
テスト();
obj.objTest();
obj.objTest2();

それは何を促すと思いますか?実行してみてください (:P);

これは関数を呼び出すオブジェクトの変更に応じて変化するので、呼び出し元のオブジェクトを強制的に変更することはできるでしょうか?答えは「はい」です。今後の記事では、この部分だけでなく、JavaScript でのさまざまなタイプのデータ メンバーの実装、クロージャ、その他の概念についても紹介する予定です。

学習過程での私の経験や洞察を書き留めることは、皆さんと共有するためであり、また、私が書いた内容に問題がある場合は、批判やアドバイスをお願いします。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。