JS での矢印関数と this の記述と理解

JS での矢印関数と this の記述と理解

序文

JavaScript は ES6 構文に矢印関数を追加しました。従来の関数と比較すると、矢印関数はより簡潔であるだけでなく、この点でも改善されています。これは JavaScript ではかなり奇妙なことです。多くの記事ではこれについてさまざまな解釈をしています。この記事では、JS における関数と this の関係を明らかにしようとします。

1. JSで関数を書く方法

1. 通常の関数の書き方

ES6 構文より前は、JS の関数は function キーワード、 params パラメータ、および中括弧で囲まれた関数本体で構成されていました。後述するアロー関数と区別するために、まずこのような関数を通常の関数と呼びます。通常の関数は、宣言型と代入型の両方で記述できます。例:

function test(name) { //宣言型の記述 console.log(name)
}
テスト('ジェリー')

let test2 = function(name) { // 割り当ての書き込み console.log(name)
}
test2('トム')

2. 矢印関数の書き方

ES6 の矢印関数の導入により、関数の記述はより簡潔になりましたが、記述する際には特定のルールに従う必要があります。

ルール1: アロー関数は宣言型ではなく代入型でのみ記述できる

例:

const テスト = (名前) => {
 console.log(名前)
}
テスト('ジェリー')

ルール 2: パラメータが 1 つしかない場合は、括弧を追加する必要はありません。パラメータがない場合、またはパラメータが複数ある場合は、括弧を追加する必要があります。

例:

const テスト = 名前 => {
 console.log(名前)
}
テスト('ジェリー')

定数テスト2 = (名前1, 名前2) => {
 console.log(name1 + ' および ' + name2)
}
test2('トム', 'ジェリー')

ルール3: 関数本体が1文だけの場合は中括弧を使う必要はありません

例:

const テスト = 名前 => console.log(名前) 

ルール4: 関数本体に括弧がない場合は、returnを書く必要はありません。矢印関数が戻り値を返すのに役立ちます。

例:

定数追加 = (p1, p2) => p1 + p2
追加(10, 25)

覚えておいてください: 関数本体の中括弧は return キーワードと一緒に使用されます。

上記の例から、矢印関数は通常の関数の括弧と中括弧の両方を簡略化することがわかります。これらの簡略化に加えて、通常の関数に対する矢印関数の最大の最適化は次のとおりです。

2. 通常の関数でこれを理解する

このための矢印関数の最適化について説明する前に、まずこれが何であるか、どのように使用されるかを理解する必要があります。これは、call メソッドを使用して関数を呼び出すときに渡される最初のパラメーターです。関数が呼び出されたときに変更できます。関数が呼び出されない場合、this の値は決定できません。

関数を呼び出すために call メソッドを使用したことがない場合は、上記の定義が明確でない可能性があります。まず関数呼び出しの 2 つの方法を理解する必要があります。

1. 純粋関数呼び出し

最初の方法が最も一般的であり、次に例を示します。

関数テスト(名前) {
 console.log(名前)
 console.log(これ)
}
test('Jerry') //関数を呼び出す

このメソッドは最もよく使用されますが、この関数呼び出しメソッドは単なる省略形です。完全な記述は次のとおりです。

関数テスト(名前) {
 console.log(名前)
 console.log(これ)
}
test.call(未定義、'トム')

上記の関数を呼び出す call メソッドに気づきましたか? call メソッドが受け取る最初のパラメーターはこれであり、ここでは undefined を渡します。それで、定義によれば、関数の実行後に入力された this は未定義になるのでしょうか?あまり。

渡したコンテキストが null または未定義の場合、ウィンドウ オブジェクトがデフォルトのコンテキストになります (厳密モードでのデフォルトのコンテキストは未定義です)。

ここで入力したのは Window オブジェクトです。

2. オブジェクト内の関数の呼び出し

直接例を見てみましょう:

定数オブジェクト = {
 名前: 'ジェリー'、
 挨拶: 関数() {
 console.log(この名前)
 }
}
obj.greet() //最初の呼び出しメソッド obj.greet.call(obj) //2番目の呼び出しメソッド

この例では、最初の呼び出しメソッドは、2 番目の呼び出しメソッドの単なる構文糖衣です。2 番目のメソッドは完全な呼び出しメソッドであり、2 番目のメソッドの強みは、これを手動で指定できることにあります。

これを手動で指定する例:

定数オブジェクト = {
 名前: 'ジェリー'、
 挨拶: 関数() {
 console.log(この名前)
 }
}
obj.greet.call({name: 'Spike'}) //出力はSpike

上記の例から、greet 関数が実行されたときにこれが変更されたことがわかります。

3. コンストラクタ内の this

コンストラクタ内の this は少し特殊です。各コンストラクタは new の後にオブジェクトを返します。このオブジェクトはコンテキストである this です。

例:

関数テスト() {
 this.name = 'トム'
}
p = 新しい Test() とする
console.log(typeof p) //オブジェクト
console.log(p.name) // トム

4. window.setTimeout() および window.setInterval() 内の関数の呼び出し

window.setTimeout() および window.setInterval() 関数内の this はやや特殊です。内部の this はデフォルトで window オブジェクトになります。

簡単にまとめると、完全な関数呼び出し方法は、test.call(context, name) や obj.greet.call(context,name) などの call メソッドを使用することです。context は関数が呼び出されたときのコンテキスト、つまり this ですが、これは call メソッドを通じて変更できます。コンストラクタは少し特殊で、その this は new の後に返されるオブジェクトを直接指します。window.setTimeout() と window.setInterval() は、デフォルトで this をウィンドウ オブジェクトに設定します。

3. 矢印関数でこれを理解する

これについては上でたくさん話しました。これは、関数が call メソッドで呼び出されたときに渡される最初のパラメーターであり、手動で変更できるため、これの値を決定するのは非常に面倒です。しかし、矢印関数の出現はこれを判断するのに役立ちます。

1. 矢印関数の機能1: 外側のthisへのデフォルトのバインディング

前述のとおり、 this の値は call メソッドを使用して変更できますが、 this の値は呼び出し時にのみ決定できます。矢印関数を使用すると、矢印関数はデフォルトで外側の this の値をバインドするため、矢印関数内の this の値は外側の this と同じになります。

矢印関数のない例:

定数オブジェクト = {
	a: 関数() { console.log(this) } 
}
obj.a() //出力はobjオブジェクトです

矢印関数の使用例:

定数オブジェクト = {
 a: () => {
 console.log(これ)
 }
}
obj.a() //出力はウィンドウ

矢印関数を使用する例では、矢印関数はデフォルトで独自の this を使用せず、外側の this と一貫性を保つため、最も外側の this は window オブジェクトになります。

2. 矢印関数の2番目の特徴: 内部で呼び出しメソッドを使用してこれを変更することはできません。

これも簡単に理解できます。関数の this は call メソッドを使用して手動で指定できることを前に説明しました。複雑さを軽減するために、矢印関数では call メソッドを使用して this を指定することはできません。

例:

定数オブジェクト = {
 a: () => {
 console.log(これ)
 }
}
obj.a.call('123') //結果は依然としてウィンドウオブジェクトです

上で、window.setTimeout() 関数のデフォルトの this は window であると述べたため、矢印関数を使用して、その this を外側の this と一致させることもできます。

window.setTimeout() の例:

定数オブジェクト = {
 a: 関数() {
 console.log(これ)
 ウィンドウ.setTimeout(() => { 
  console.log(これ) 
 }, 1000)
 }
}
obj.a.call(obj) //最初の this は obj オブジェクト、2 番目の this も obj オブジェクト

関数 obj.a は矢印関数を使用していないことは誰もが理解していると思います。その理由は、その this が依然として obj であり、setTimeout 内の関数が矢印関数を使用しているため、これも obj である外側の this と一貫性があるからです。setTimeout 内の関数が矢印関数を使用しない場合は、window オブジェクトとして入力する必要があります。

4. 多層オブジェクトネストにおけるこの関数

ここで私が勉強中に遭遇したちょっとした混乱について述べます。矢印関数の this は外側のレイヤーと一致していますが、この外側のレイヤーに複数のレイヤーがある場合、どのレイヤーと一致しているのでしょうか?

直接例を見てみましょう:

定数オブジェクト = {
 a: 関数() { console.log(this) },
 b: {
 	c: 関数() {console.log(this)}
	}
}
obj.a() // obj オブジェクトを出力します。obj.a.call(obj) と同等です。
obj.bc() // obj.b オブジェクトを出力します。これは obj.bccall(obj.b) と同等です。

上記のコードはすべて直感に沿ったものです。次に、obj.bc に対応する関数を矢印関数に置き換えると、結果は次のようになります。

定数オブジェクト = {
 a: 関数() { console.log(this) },
 b: {
 	c: () => {console.log(これ)}
	}
}
obj.a() //矢印関数なしの出力はobjです
obj.bc() // 印刷されるのはウィンドウ オブジェクトです。 !

obj.a を呼び出した後、obj オブジェクトが出力されますが、obj.bc を呼び出した後、obj の代わりに window オブジェクトが出力されます。これは、複数レイヤーのオブジェクトのネストでは、矢印関数の this が最も外側のレイヤーと一致していることを意味します。

上記内容は著者がアロー関数を学ぶ際に整理した知識ポイントです。間違いがあればご指摘・ご訂正をお願いします!これは私が Nuggets について書いた 3 番目の記事です。読んでいただきありがとうございます。

この記事の参照: これの価値は何ですか?一度明確にする

要約する

これで、JS で矢印関数と this を記述して理解する方法に関するこの記事は終了です。より関連性の高い JS 矢印関数と this コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JavaScript の基本を詳しく分析: this 関数と矢印関数
  • JavaScriptの矢印関数での詳細な説明
  • JavaScriptの矢印関数の詳細な理解
  • JSの矢印関数におけるこのポイントの詳細な説明

<<:  JavaScriptの詳細な説明 thisキーワード

>>:  js での遅延読み込みとプリロードの具体的な使用法

推薦する

Docker イメージのデフォルトの保存場所を変更する方法 (ソリューション)

システムの初期のパーティション分割により、オペレーティング システム内の対応する / パーティション...

Kylin V10 サーバーで Storm をコンパイルしてインストールする詳細なプロセス

1 はじめにApache Storm は、Hadoop と同様に、大量のデータを処理するために使用で...

Vant Uploaderは1枚以上の写真をアップロードするコンポーネントを実装します

この記事では、1枚以上の写真をアップロードするためのVant Uploaderコンポーネントを紹介し...

マークアップ言語 -

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

MySQL InnoDBとMyISAMの違いを簡単に理解する

序文MySQL は、myisam、innodb、memory、archive、example など、...

JavaScript で 24 以上の配列メソッドを手動で実装する

目次1. トラバーサルクラス1. 各2. 地図3. すべての4. いくつか5. フィルター6. 減ら...

MySQL で重複行を見つけて削除する方法

目次1. 重複行を見つける方法2. 重複行を削除する方法3. 複数の列で重複を見つける方法4. クエ...

Linuxシステムにmsfをインストールするプロセスの詳細な説明

または、インストールプロセスを自分で書き留めてください。私のサーバーシステムはAliyun Linu...

JavaScript オブジェクトを作成する 3 つの方法

目次1. オブジェクトリテラル2. newキーワードはオブジェクトを作成する3. Object.cr...

js 基本構文と Maven プロジェクト構成チュートリアル ケース

目次1. jsステートメント2番目、js配列3. js関数4. メイヴンV. 結論1. jsステート...

Linux システムのスワップ領域の紹介

スワップ スペースは、オペレーティング システムに関係なく、今日のコンピューティングの一般的な側面で...

JS関数の呼び出し、適用、バインドの超詳細な方法

目次JS 関数呼び出し、適用、バインドメソッド1. call() メソッド1. call() メソッ...

CocosCreator システムイベントがどのように生成され、トリガーされるかについての詳細な説明

目次環境まとめモジュール機能関連文書ソースコード分析CCGame.js CCInputManager...

Linux に MySQL をインストールする方法 (yum とソース コードのコンパイル)

Linux に MySQL をインストールするには、yum インストールとソース コード コンパイ...

MySQL 5.7.21 解凍版のインストールと設定方法のグラフィックチュートリアル (win10)

MySQL 5.7.21 解凍版のインストールと設定方法は参考までに。具体的な内容は以下のとおりで...