JavaScript:平易な言葉でのスコープ

良い一日、友達!



スコープは、変数のアクセス可能性を決定する上で重要な概念です。この概念はクロージャの中心であり、変数をグローバルとローカルに分割します。



この記事では、JavaScriptのスコープとは何かを簡単に説明しようと思います。



1.範囲



スコープの詳細に飛び込む前に、簡単な例を見てみましょう。



変数を定義したとしましょう:



const message = 'Hello'
console.log(message) // 'Hello'


その値をコンソールに簡単に出力できます。これは明らかです。



次に、メッセージ変数の宣言をifブロックに配置しましょう。



if (true) {
    const message = 'Hello'
}
console.log(message) // ReferenceError: message is not defined


今回、変数にアクセスしようとすると、ReferenceError:メッセージが定義されていませんという例外がスローされます。



なぜこれが起こったのですか?



ifブロックがメッセージ変数のスコープを作成したためです。また、メッセージはこのスコープ内でのみ使用できます。







したがって、変数の可用性は、それらが定義されているスコープによって制限されます。



したがって、スコープは変数のスコープです。



2.ブロックスコープ



JavaScriptのコードのブロックは、constおよびletキーワードで宣言された変数のスコープを定義します。



if (true) {
    //    if
    const message = 'Hello'
    console.log(message) // 'Hello'
}
console.log(message) // ReferenceError


最初のconsole.log()は、メッセージ変数の値をコンソールに安全に出力します。これは、この変数が定義されているスコープでアクセスされるためです。



ただし、2番目のconsole.log()を呼び出すと、メッセージ変数がその外部スコープで使用できないため、エラーが生成されます。メッセージは現在のコンテキストに存在しません。



ブロックスコープは、if、for、whileステートメントにも作成されます。



例えば:



for (const color of ['green', 'red', 'blue']) {
    //    for
    const message = 'Hi'
    console.log(color) // 'green', 'red', 'blue'
    console.log(message) // 'Hi', 'Hi', 'Hi'
}
console.log(color) // ReferenceError
console.log(message) // ReferenceError


color変数とmessage変数は、forブロック内にのみ存在します。



whileステートメントについても同じことが言えます。



while (/*  */) {
    //    while
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


whileで定義されたメッセージは、このループ内でのみ使用できます。



JavaScriptでは、自己完結型のコードブロックを作成できます。また、独自のスコープを定義します。



{
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


2.1。varはブロックスコープではありません



前の例で見たように、コードのブロックは、constおよびletキーワードで宣言された変数のスコープを作成します。ただし、これはvarキーワードで宣言された変数では機能しません。



例を考えてみましょう:



if (true) {
    //    if
    var count = 0
    console.log(count) // 0
}
console.log(count) // 0


予想どおり、変数countはifブロック内で使用できます。ただし、このブロックの外でも利用できます!



重要なのは、コードブロックはvarキーワードで宣言された変数のスコープを作成しないということです。しかし、関数はそれを行います。



3.機能範囲



JavaScriptの関数は、宣言されているキーワード(var、const、またはlet)に関係なく、すべての変数のスコープを作成します。



例えば:



function run() {
    //    run()
    var message = ', , !'
    console.log(message)
}
run() // ', , !'
console.log(message) // ReferenceError


run()関数はスコープを作成します。可変メッセージは関数の内部で使用できますが、外部では使用できません。



同様に、この関数は、constとletで宣言された変数、さらには他の関数や関数式のスコープを作成します。



function run() {
    //    run()
    const two = 2
    let one = 1
    function run2() {}
    var run3 = () => {}

    console.log(two)
    console.log(one)
    console.log(run2)
    console.log(run3)
}
run() // 2 1 ƒ run2() {} () => {}
console.log(two) // ReferenceError
console.log(one) // ReferenceError
console.log(run2) // ReferenceError
console.log(run3) // ReferenceError


4.モジュールの可視性



ES6モジュールは、変数、関数、およびクラスのスコープも作成します。



サークルモジュールは、定数piを作成します(内部使用用)。



//    circle
const pi = 3.14

console.log(pi) // 3.14

//  pi


pi変数は、サークルモジュール内で宣言され、そこからエクスポートされません。



次に、サークルモジュールがインポートされます。



import './circle'

console.log(pi) // ReferenceError


変数piは、サークルモジュールの外部では使用できません(exportを使用してエクスポートされるまで)。



モジュラースコープはモジュールをカプセル化します。これは、プライベート変数(エクスポートされない)がモジュール自体のニーズに使用され、外部アクセスから保護されることを意味します。



したがって、スコープは、コード、関数、およびモジュールのブロックのカプセル化メカニズムであると言えます。



5.スコープはネストできます



スコープの興味深い機能は、スコープを相互にネストできることです。



次の例では、run()関数がスコープを作成し、その内部でifブロックが別のスコープを作成します。



function run() {
    //    run()
    const message = ', , !'

    if (true) {
        //    if
        const friend = ''
        console.log(message) // ', , !'
    }

    console.log(friend) // ReferenceError
}
run()


ifブロックのスコープは、run()関数のスコープ内にネストされています。



別のスコープ内にあるスコープは、内部スコープと呼ばれます。上記の例では、これがifブロックのスコープです。



別のスコープを含むスコープは、外部スコープと呼ばれます。上記の例では、これはrun()関数のスコープです。







可変可用性についてはどうですか?覚えておくべき簡単なルールは次のとおりです。



外部スコープの変数は、内部スコープで使用できます。



したがって、メッセージ変数はifブロック内で使用できます。



6.グローバルスコープ



グローバルスコープは最も外側のスコープです。これは、内部スコープまたはローカルスコープで使用できます。ブラウザでは、scriptタグのsrc属性で指定されたJavaScriptファイルがロードされると、グローバルスコープが作成されます。



<script src="script.js">




// script.js

//グローバルスコープletcounter

= 1



グローバルスコープで宣言された変数はグローバル変数です。それらは他のどの地域でも利用できます。



グローバルスコープは、JavaScriptランタイム(ブラウザ、Node.js)がホスト(つまり、環境所有)オブジェクトをグローバル変数としてアプリケーションに公開できるようにするメカニズムです。



たとえば、ウィンドウとドキュメントは、ブラウザによって提供されるグローバル変数(オブジェクト)です。Node.jsでは、このような変数は、たとえば、プロセスオブジェクトです。



7.字句スコープ



2つの関数を定義しましょう。一方は他方の中にネストされています。



function outer() {
    //    outer()
    let v = '     outer()!'

    function inner() {
        //    inner()
        console.log(v) // '     outer()!'
    }

    return inner
}

const f = outer()
f()


最後の行を見てください。inner()はouter()のスコープ外で呼び出されます。 JavaScriptは、inner()関数でコンソールに出力された値がouter()関数で宣言された変数vに属していることをどのように認識しますか?



回答:字句スコープに感謝します。



JavaScriptは、字句または静的スコープと呼ばれるメカニズムを実装します。字句スコープとは、変数のアクセス可能性が、ネストされた関数のスコープ内のこれらの変数の位置によって静的に決定されることを意味します。外部関数のスコープからの変数は、ネストされた関数のスコープで使用できます。



字句スコープの正式な定義は次のとおりです。



字句スコープは、静的に定義された外部スコープで構成されます。外側の領域から、内側の関数でそれらの領域の変数を使用して修正されました。



上記の例では、inner()関数の字句スコープはouter()関数のスコープで構成されています。



さらに、inner()は、字句スコープの変数の値を使用するため、クロージャーです。



8.変数の分離



明らかに、スコープは変数を分離します。これにより、異なるスコープに同じ名前の変数を含めることができます。



変数count、index、current、valueなどを使用できます。衝突(名前の衝突)の脅威なしにさまざまな領域で。



例えば:



function foo() {
    //    foo()
    let count = 1
    console.log(count) // 1
}

function bar() {
    //    bar()
    let count = 2
    console.log(count) // 2
}

foo()
bar()


結論



スコープは、変数の可用性を決定します。現在のスコープで宣言された変数は、そのスコープ内でのみ使用できます。



JavaScriptでは、スコープはブロック、関数、およびモジュールによって作成されます。



constおよびletキーワードで宣言された変数は、ブロック、機能、またはモジュラーにすることができますが、varキーワードで宣言された変数はブロックスコープではありません。



スコープはネストできます。外側のスコープで宣言された変数は、内側のスコープで使用できます。



字句スコープは、静的に定義された外部スコープで構成されます。すべての関数は、実行される場所に関係なく、字句スコープから変数にアクセスできます(これがクロージャーの本質です)。



この記事がお役に立てば幸いです。清聴ありがとうございました。



All Articles