JavaScript のスコープとコンテキストは、JavaScript がもたらす柔軟性のおかげで、この言語に固有です。各関数には異なる変数コンテキストとスコープがあります。これらの概念は、JavaScript のいくつかの強力なデザイン パターンの基礎となっています。ただし、これは開発者に大きな混乱をもたらします。以下では、JavaScript におけるコンテキストとスコープの違いと、さまざまなデザイン パターンでそれらがどのように使用されるかを包括的に明らかにします。
コンテキストとスコープ
最初に明確にする必要があるのは、コンテキストとスコープは異なる概念であるということです。長年にわたり、多くの開発者がこれら 2 つの用語を混同し、一方をもう一方と誤って説明していることに気づきました。公平を期すために言うと、これらの用語は非常にわかりにくいものになっています。
各関数呼び出しには、スコープとそれに関連付けられたコンテキストがあります。基本的に、スコープは関数ベースであり、コンテキストはオブジェクトベースです。言い換えれば、スコープは各関数呼び出しでの変数へのアクセスに関連しており、各呼び出しは独立しています。コンテキストは常にキーワード this の値であり、現在の実行可能コードを呼び出すオブジェクトへの参照です。
変数スコープ
変数はローカル スコープまたはグローバル スコープで定義でき、その結果、異なるスコープからランタイム変数にアクセスできます。グローバル変数は関数本体の外側で宣言する必要があり、実行中のプロセス全体に存在し、どのスコープでもアクセスおよび変更できます。ローカル変数は関数本体内でのみ定義され、関数呼び出しごとに異なるスコープを持ちます。このトピックは呼び出し内のみの値の割り当て、評価、操作であり、スコープ外の値にはアクセスできません。
現在、JavaScript はブロックレベルのスコープをサポートしていません。ブロックレベルのスコープとは、if ステートメント、switch ステートメント、loop ステートメントなどのステートメント ブロック内の変数の定義を指します。これは、ステートメントの外部で変数にアクセスできないことを意味します。ブロック。現在、ステートメント ブロック内で定義されている変数は、ステートメント ブロックの外部からアクセスできます。ただし、let キーワードが ES6 仕様に正式に追加されたため、これは間もなく変更されます。ローカル変数をブロックレベルのスコープとして宣言するには、var キーワードの代わりにこれを使用します。
「この」コンテキスト
コンテキストは通常、関数の呼び出し方法によって異なります。関数がオブジェクトのメソッドとして呼び出される場合、これはメソッドが呼び出されるオブジェクトに設定されます:
var object = {
foo: function(){
alert(this === object); >};
object.foo(); // true
new 演算子を使用してオブジェクトのインスタンスを作成する関数を呼び出す場合にも同じ原則が適用されます。この方法で呼び出すと、this の値は新しく作成されたインスタンスに設定されます:
foo() // ウィンドウ
new foo() // foo
アンバインド関数を呼び出すと、これはデフォルトでグローバル コンテキストまたはウィンドウ オブジェクト (ブラウザー内の場合) に設定されます。ただし、関数が strict モード (「use strict」) で実行される場合、この値はデフォルトで undefine に設定されます。
実行コンテキストとスコープ チェーン
JavaScript はシングルスレッド言語です。つまり、ブラウザーで同時に実行できる処理は 1 つだけです。 JavaScript インタープリターが最初にコードを実行するとき、最初はデフォルトでグローバル コンテキストが使用されます。関数が呼び出されるたびに、新しい実行コンテキストが作成されます。
ここでの「実行コンテキスト」という用語は、上で説明したコンテキストではなくスコープを意味します。これは不適切な命名ですが、この用語は ECMAScript 仕様によって定義されており、それに従う以外に選択肢はありません。
新しい実行コンテキストが作成されるたびに、スコープ チェーンの先頭に追加され、実行スタックまたは呼び出しスタックにもなります。ブラウザは常に、スコープ チェーンの最上位にある現在の実行コンテキストで実行されます。完了すると、それ (現在の実行コンテキスト) はスタックの最上位から削除され、制御は前の実行コンテキストに戻ります。例:
3番目();
関数3番目(){
関数4番目();何か
}
}
}
}
first();
前のコードを実行すると、ネストされた関数が上から下に 4 番目の関数まで実行されます。このとき、スコープ チェーンは上から下に 4 番目、3 番目、2 番目、1 番目、グローバルになります。 4 番目の関数は、グローバル変数と、独自の変数と同様に、1 番目、2 番目、および 3 番目の関数で定義された変数にアクセスできます。 4 番目の関数の実行が完了すると、4 番目のコンテキストがスコープ チェーンの先頭から削除され、実行は 3 番目の関数に戻ります。このプロセスは、すべてのコードの実行が完了するまで継続されます。
異なる実行コンテキスト間の変数名の競合は、ローカルからグローバルまでスコープ チェーンを登ることによって解決されます。これは、同じ名前のローカル変数がスコープ チェーン内でより高い優先順位を持つことを意味します。
簡単に言えば、関数実行コンテキストで変数にアクセスしようとするたびに、検索プロセスは常に独自の変数オブジェクトから開始されます。探している変数が独自の変数オブジェクト内に見つからない場合は、スコープ チェーンの検索を続けます。スコープ チェーンをたどり、各実行コンテキスト変数オブジェクトを調べて、変数名に一致する値を見つけます。
クロージャ
入れ子の関数がその定義 (スコープ) の外でアクセスされ、外側の関数が戻った後に実行できるようにすると、クロージャが形成されます。これ (クロージャ) は、外部関数のローカル変数、引数、関数宣言への (内部関数内での) アクセスを維持します。カプセル化により、実行コンテキストを外部スコープから隠して保護しながら、さらなる操作を実行できるパブリック インターフェイスを公開できます。簡単な例は次のようになります。
function foo() {
var local = 'プライベート変数';
return function bar(){
return local;
}
var getLocalVariable = foo() ;
getLocalVariable() // プライベート変数
var privateProperty = 'foo';
function privateMethod(args){
//何かをする
}
return {
publicProperty: "",
publicMethod: function(args){
//何かをする
},
privilegedMethod: function(args) ){
privateMethod(args);
}
}
})();
別のタイプのクロージャは、即時呼び出し関数式 IIFE と呼ばれます。これは、ウィンドウ コンテキストで自己呼び出しされる匿名関数にすぎません。
var a = 'foo', b = 'bar';
function private(){
// 何かを実行します
}
window.Module = {
public: function(){
// 何かをします
}
}
})(this);グローバル名前空間。この式は非常に便利です。関数本体内で宣言されたすべての変数はローカル変数であり、クロージャを通じてランタイム環境全体にわたって持続します。ソース コードをカプセル化するこの方法は、プログラムとフレームワークの両方で非常に一般的であり、通常は外部と対話するための単一のグローバル インターフェイスを公開します。
は、カスタム コンテキストで関数を実行できるようにするすべての関数に組み込まれている 2 つの単純なメソッドです。 call 関数にはパラメータ リストが必要で、apply 関数ではパラメータを配列として渡すことができます。
コードをコピー
user.apply (ウィンドウ, ['ジョン', 'Doe', 30]);
実行結果は同じです。ユーザー関数はウィンドウ コンテキストで呼び出され、同じ 3 つのパラメーターが提供されます。
ECMAScript 5 (ES5) では、コンテキストを制御する Function.prototype.bind メソッドが導入され、この関数 (コンテキスト) は、バインド メソッドの最初のパラメーターに永続的にバインドされます。関数の呼び出し方法。クロージャを通じて関数のコンテキストを修正します。サポートされていないブラウザの場合の解決策は次のとおりです。
if(!('bind' in Function.prototype)){
Function.prototype.bind = function(){
var fn = this, context = argument[ 0] 、args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args);
}
これは、オブジェクト指向やイベント処理などのコンテキスト損失でよく使用されます。これが必要なのは、ノードの addEventListener メソッドがイベント ハンドラーがバインドされているノードとして関数実行のコンテキストを常に維持するためであり、これが重要です。ただし、高度なオブジェクト指向技術を使用し、コールバック関数のコンテキストをメソッドのインスタンスとして維持する必要がある場合は、コンテキストを手動で調整する必要があります。これはバインドによってもたらされる利便性です:
this.element.addEventListener('click', this.onClick.bind(this), false);
🎜>
MyClass.prototype.onClick = function(e){
// do something
};
バインド関数のソース コードを振り返ると、次の行は、配列のメソッドを呼び出す比較的単純なコードであることに気づくかもしれません:
興味深いことに、ここで、引数オブジェクトは実際には配列ではないことに注意してください。多くの場合、配列のような ) オブジェクトとして説明されます。これは、nodelist (document.getElementsByTagName() メソッド) によって返される結果です。これらには長さ属性が含まれており、値にインデックスを付けることができますが、スライスやプッシュなどのネイティブの配列メソッドをサポートしていないため、配列ではありません。ただし、配列と同様に動作するため、配列メソッドを呼び出してハイジャックすることができます。配列のようなコンテキストで配列メソッドを実行する場合は、上記の例に従ってください。
}
サブクラス (MyClass) のインスタンスでスーパークラス (MySuperClass) のメソッドを呼び出すことによって、この強力なデザインパターンを再現できます。
結論
最新の JavaScript ロールではスコープとコンテキストが重要かつ基本的な役割を果たすため、高度なデザイン パターンを学習し始める前にこれらの概念を理解することが非常に重要です。クロージャ、オブジェクト指向、継承、またはさまざまなネイティブ実装について話す場合でも、コンテキストとスコープが重要な役割を果たします。 JavaScript 言語をマスターし、そのコンポーネントを深く理解することが目標の場合、スコープとコンテキストを出発点にする必要があります。
翻訳者の補足
作者が実装したバインド関数は、bind によって返される関数を呼び出すときにパラメータを渡すことができません。次のコードはこの問題を修正します。 🎜>
コードをコピーします
return fn.apply(context, args.concat(arguments));//修正
}
}
}

packagemainimport"fmt"funcmain(){x:=10switchx{case0:y:='a'fmt.Printf("%c\n",y)case1://y='b'//thiscan'tcompile,y:='b'fmt.Printf("%c\n",y)default:y:=

在Linux多线程编程中,锁是一种非常重要的机制,可以避免线程间的竞争和死锁。然而,如果不正确使用锁,可能会导致性能下降和不稳定的行为。本文将介绍Linux中的常见锁类型,如何正确使用它们,以及如何避免竞争和死锁等问题。在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为”互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。Linux实现的互斥锁机制包括POSIX互斥锁和内核互斥锁,本文主要讲POSIX互斥锁,即线程间互斥锁。信号量用在多线程

Golang函数中的变量作用域详解在Golang中,变量的作用域指的是变量的可访问范围。了解变量的作用域对于代码的可读性和维护性非常重要。在本文中,我们将深入探讨Golang函数中的变量作用域,并提供具体的代码示例。在Golang中,变量的作用域可以分为全局作用域和局部作用域。全局作用域指的是在所有函数外部声明的变量,即在函数之外定义的变量。这些变量可以在整

pythonLambda表达式是一个小的匿名函数,它可以将一个表达式存储在变量中并返回它的值。Lambda表达式通常用于执行简单的任务,这些任务可以通过编写一个单独的函数来完成,但Lambda表达式可以使代码更简洁和易读。Lambda表达式的语法如下:lambdaarguments:expressionarguments是Lambda表达式接收的参数列表,expression是Lambda表达式的体,它包含需要执行的代码。例如,以下Lambda表达式将两个数字相加并返回它们的和:lambdax,

掌握JavaScript函数的嵌套和作用域,需要具体代码示例在JavaScript编程中,函数是非常重要的概念。函数的嵌套和作用域能够极大地提高代码的可读性和灵活性。本文将介绍如何正确地使用嵌套函数和作用域,并提供具体的代码示例。函数的嵌套可以理解为在一个函数中定义了另一个函数。这种嵌套的方式能够将代码分成多个小块,使得程序的逻辑更加清晰。同时,嵌套函数还可

JavaScript中const的作用和用法JavaScript是一种广泛应用于网页开发的编程语言,其具有灵活性和动态性是其特点之一。在JavaScript中,我们可以使用const关键字来声明一个常量。本文将介绍const关键字的作用和用法,并提供一些具体的代码示例来帮助读者更好地理解。const的作用const(常量)是一种用于声明不可更改的变量的关键字

c语言static的作用和用法:1、变量作用域;2、生命周期;3、函数内部;4、修饰全局变量;5、修饰函数;6、其他用途;详细介绍:1、变量作用域,当一个变量前有static关键字,那么这个变量的作用域被限制在声明它的文件内,也就是说,这个变量是“文件级作用域”,这对于防止变量的“重复定义”问题很有用;2、生命周期,静态变量在程序开始执行时初始化一次,并在程序结束时销毁等等。

Python是一种高级编程语言,它的易用性和流行程度使得它成为了众多程序员的首选语言。与其他语言一样,Python也存在一些常见的错误类型,例如变量未定义错误。当我们在Python中使用一个未定义的变量时,程序就会抛出一个名为“NameError”的异常。这种错误通常出现在以下几种情况下:拼写错误:可能是因为变量名拼写错误导致了变量未定义错误,我们需要仔细检


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

Dreamweaver Mac版
ビジュアル Web 開発ツール

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

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

ホットトピック



