検索
ホームページウェブフロントエンドjsチュートリアルJavaScriptのスコープとクロージャの詳細な説明

スコープとクロージャはJavaScriptにおいて非常に重要です。しかし、初めて JavaScript を学んだときは、理解するのが難しかったです。まずはスコープから始めましょう。この記事では主に JavaScript のスコープとクロージャについて紹介し、JavaScript のスコープとクロージャをより深く理解できるようにしたいと考えています。

スコープ

JavaScript スコープは、アクセスできる変数を制限します。スコープには、グローバル スコープとローカル スコープの 2 種類があります。

グローバル スコープ

すべての関数宣言または中括弧の外側で定義された変数は、グローバル スコープ内にあります。

ただし、このルールはブラウザーで実行される JavaScript でのみ有効です。 Node.js を使用している場合、グローバル スコープの変数は異なりますが、この記事では Node.js については説明しません。

`const globalVariable = 'some value'`

グローバル変数を宣言すると、関数内を含むどこでもそれを使用できます。

const hello = 'Hello CSS-Tricks Reader!'

function sayHello () {
 console.log(hello)
}

console.log(hello) // 'Hello CSS-Tricks Reader!'
sayHello() // 'Hello CSS-Tricks Reader!'

グローバル スコープで変数を定義できますが、それはお勧めしません。名前の競合が発生する可能性があるため、2 つ以上の変数が同じ変数名を使用します。変数を定義するときに const または let を使用すると、名前の競合があるとエラーが発生します。これはお勧めできません。

// Don't do this!
let thing = 'something'
let thing = 'something else' // Error, thing has already been declared

変数を定義するときに var を使用すると、2 番目の定義が最初の定義を上書きします。これにより、コードのデバッグが困難になるため、望ましくありません。

// Don't do this!
var thing = 'something'
var thing = 'something else' // perhaps somewhere totally different in your code
console.log(thing) // 'something else'

そのため、グローバル変数の代わりにローカル変数を使用するようにしてください

ローカルスコープ

コードの特定のスコープで使用される変数は、ローカルスコープで定義できます。これはローカル変数です。

JavaScript には、関数スコープとブロックレベル スコープの 2 種類のローカル スコープがあります。

関数スコープから始めます。

関数スコープ

関数内で変数を定義すると、その変数は関数内のどこでも使用できます。関数の外からはアクセスできません。

たとえば、次の例では、sayHello 関数の hello 変数:

function sayHello () {
 const hello = 'Hello CSS-Tricks Reader!'
 console.log(hello)
}

sayHello() // 'Hello CSS-Tricks Reader!'
console.log(hello) // Error, hello is not defined

ブロックレベルのスコープ

中括弧を使用して const 変数または let 変数を宣言する場合、この変数は中括弧内でのみ使用できます。

次の例では、hello は中括弧内でのみ使用できます。

{
 const hello = 'Hello CSS-Tricks Reader!'
 console.log(hello) // 'Hello CSS-Tricks Reader!'
}

console.log(hello) // Error, hello is not defined

関数は中括弧で定義する必要があるため (明示的に return ステートメントとアロー関数を使用しない限り)、ブロックレベルのスコープは関数スコープのサブセットです。

関数の昇格とスコープ

関数を使用して定義すると、その関数は現在のスコープの先頭に昇格されます。したがって、次のコードは同等です:

// This is the same as the one below
sayHello()
function sayHello () {
 console.log('Hello CSS-Tricks Reader!')
}

// This is the same as the code above
function sayHello () {
 console.log('Hello CSS-Tricks Reader!')
}
sayHello()

関数式を使用して定義された場合、関数は変数スコープの先頭にホイストされません。

sayHello() // Error, sayHello is not defined
const sayHello = function () {
 console.log(aFunction)
}

ここには 2 つの変数があるため、関数のホイスティングは混乱を引き起こす可能性があるため、機能しません。したがって、関数を使用する前に必ず定義してください。

関数は他の関数のスコープにアクセスできません

異なる関数が個別に定義されている場合、1 つの関数内で関数を呼び出すことはできますが、ある関数は他の関数のスコープにアクセスすることはできません。

次の例では、2 番目は firstFunctionVariable 変数にアクセスできません。

function first () {
 const firstFunctionVariable = `I'm part of first`
}

function second () {
 first()
 console.log(firstFunctionVariable) // Error, firstFunctionVariable is not defined
}

ネストされたスコープ

関数が関数内で定義されている場合、内側の関数は外側の関数の変数にアクセスできますが、その逆はできません。その効果は字句スコープです。

外部関数は内部関数の変数にアクセスできません。

function outerFunction () {
 const outer = `I'm the outer function!`

 function innerFunction() {
  const inner = `I'm the inner function!`
  console.log(outer) // I'm the outer function!
 }

 console.log(inner) // Error, inner is not defined
}

スコープの仕組みをイメージすると、ツーウェイミラー(片面シースルーガラス)をイメージできます。中からは外が見えますが、外の人からは見えません。

関数スコープは二面鏡のようなものです。中からは外が見えますが、外からは見えません。

ネストされたスコープも同様のメカニズムですが、より多くの双方向ミラーを持つことと同等です。

多層機能とは、複数の双方向ミラーを意味します。

スコープに関する前の部分を理解すると、クロージャが何であるかを理解できます。

クロージャー

関数内に別の関数を作成する場合、それはクロージャーを作成することと同じです。内部関数はクロージャです。通常、外部関数の内部変数にアクセスできるようにするために、このクロージャが返されるのが一般的です。

function outerFunction () {
 const outer = `I see the outer variable!`

 function innerFunction() {
  console.log(outer)
 }

 return innerFunction
}

outerFunction()() // I see the outer variable!

内部関数は値を返すため、関数宣言部分を簡素化できます:

function outerFunction () {
 const outer = `I see the outer variable!`

 return function innerFunction() {
  console.log(outer)
 }
}

outerFunction()() // I see the outer variable!

クロージャは外部関数の変数にアクセスできるため、通常、次の 2 つの用途があります:

  1. 副作用を減らす

  2. プライベート変数を作成する

クロージャを使用して副作用を制御する

関数が値を返すときに何かを実行すると、通常、何らかの副作用が発生します。副作用は、Ajax 呼び出し、タイムアウト、さらには console.log 出力ステートメントなど、さまざまな状況で発生する可能性があります:

function (x) {
 console.log('A console.log is a side effect!')
}

クロージャーを使用して副作用を制御する場合、コードの動作を混乱させる可能性があるものを実際に考慮する必要があります。 Ajax やタイムアウトなどのプロセス。

物事を明確に説明するには、例を見るとより便利です:

比如说你要给为你朋友庆生,做一个蛋糕。做这个蛋糕可能花1秒钟的时间,所以你写了一个函数记录在一秒钟以后,记录做完蛋糕这件事。

为了让代码简短易读,我使用了ES6的箭头函数:

function makeCake() {
 setTimeout(_ => console.log(`Made a cake`, 1000)
 )
}

如你所见,做蛋糕带来了一个副作用:一次延时。

更进一步,比如说你想让你的朋友能选择蛋糕的口味。那么你就给做蛋糕makeCake这个函数加了一个参数。

function makeCake(flavor) {
 setTimeout(_ => console.log(`Made a ${flavor} cake!`, 1000))
}

因此当你调用这个函数时,一秒后这个新口味的蛋糕就做好了。

makeCake('banana')
// Made a banana cake!

但这里的问题是,你并不想立刻知道蛋糕的味道。你只需要知道时间到了,蛋糕做好了就行。

要解决这个问题,你可以写一个prepareCake的功能,保存蛋糕的口味。然后,在返回在内部调用prepareCake的闭包makeCake。

从这里开始,你就可以在你需要的时调用,蛋糕也会在一秒后立刻做好。

function prepareCake (flavor) {
 return function () {
  setTimeout(_ => console.log(`Made a ${flavor} cake!`, 1000))
 }
}

const makeCakeLater = prepareCake('banana')

// And later in your code...
makeCakeLater()
// Made a banana cake!

这就是使用闭包减少副作用:你可以创建一个任你驱使的内层闭包。

私有变量和闭包

前面已经说过,函数内的变量,在函数外部是不能访问的既然不能访问,那么它们就可以称作私有变量。

然而,有时候你确实是需要访问私有变量的。这时候就需要闭包的帮助了。

function secret (secretCode) {
 return {
  saySecretCode () {
   console.log(secretCode)
  }
 }
}

const theSecret = secret('CSS Tricks is amazing')
theSecret.saySecretCode()
// 'CSS Tricks is amazing'

这个例子里的saySecretCode函数,就在原函数外暴露了secretCode这一变量。因此,它也被成为特权函数。

使用DevTools调试

Chrome和Firefox的开发者工具都使我们能很方便的调试在当前作用域内可以访问的各种变量一般有两种方法。

第一种方法是在代码里使用debugger关键词。这能让浏览器里运行的JavaScript的暂停,以便调试。

下面是prepareCake的例子:

function prepareCake (flavor) {
 // Adding debugger
 debugger
 return function () {
  setTimeout(_ => console.log(`Made a ${flavor} cake!`, 1000))
 }
}

const makeCakeLater = prepareCake('banana')

打开Chrome的开发者工具,定位到Source页下(或者是Firefox的Debugger页),你就能看到可以访问的变量了。

使用debugger调试prepareCake的作用域。

你也可以把debugger关键词放在闭包内部。注意对比变量的作用域:

function prepareCake (flavor) {
 return function () {
  // Adding debugger
  debugger
  setTimeout(_ => console.log(`Made a ${flavor} cake!`, 1000))
 }
}

const makeCakeLater = prepareCake('banana')

调试闭包内部作用域

第二种方式是直接在代码相应位置加断点,点击对应的行数就可以了。

通过断点调试作用域

总结一下

闭包和作用域并不是那么难懂。一旦你使用双向镜的思维去理解,它们就非常简单了。

当你在函数里声明一个变量时,你只能在函数内访问。这些变量的作用域就被限制在函数里了。

如果你在一个函数内又定义了内部函数,那么这个内部函数就被称作闭包。它仍可以访问外部函数的作用域。

相关推荐:

详解JavaScript作用域和闭包

javascript 词法作用域和闭包分析说明_javascript技巧

深入理解javascript作用域和闭包_基础知识

以上がJavaScriptのスコープとクロージャの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター