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 での遅延読み込みとプリロードの具体的な使用法

推薦する

MySQL マスタースレーブスイッチチャネルの問題の解決策

VIP を設定した後、アクティブ/スタンバイの切り替え中に表示されるエラー メッセージは次のとおりで...

MySQL の永続性とロールバックの原理を 1 つの記事で理解する

目次再実行ログディスクデータを直接更新するのではなく、最初にメモリデータを更新する必要があるのはなぜ...

Vue Element UIの使用時に遭遇した問題をまとめる

目次1. DateTimePickerの日付選択範囲は現在時刻とそれ以前です2. DateTimeP...

ウェブページ作成のヒントのまとめ

序文この記事は主に、日常の Web ページ制作で遭遇する問題解決スキルの一部をまとめ、皆さんの参考と...

Docker実行コンテナが作成状態にある問題についての簡単な説明

最近の問題としては、次のような現象があります。システムには、docker run コマンドを継続的に...

Zabbix上のすべてのホストのIPとホスト名を取得する

ザビックスZabbix ([`zæbiks]) は、WEB インターフェースに基づいて分散システム監...

du コマンドを使用して Linux システム ディレクトリのサイズを取得する方法

Linux システムを使用したことがある人なら、Linux システムの ls コマンドは通常、ファイ...

Vueリスナーの使用例の詳細な説明

1つ目はjQueryのajaxを使用してリクエストを送信することです ユーザーが登録するときに、リス...

XHTML の珍しいが便利なタグ

Xhtml には、あまり使用されないが非常に便利なタグが多数あります。半分の労力で 2 倍の結果を達...

Linux サービスでファイアウォールを有効にする 2 つの方法

方法は2つあります: 1. サービス方法ファイアウォールのステータスを確認します。 [root@ce...

CentOS 8 / RHEL 8 に VirtualBox 6.0 をインストールするための詳細なチュートリアル

VirtualBox は、技術者が異なる種類の複数の仮想マシン (VM) を同時に実行できるようにす...

MySQL Innodbの主な機能挿入バッファ

目次挿入バッファとは何ですか?挿入バッファのトリガー条件は何ですか?なぜ一意のインデックスにできない...

MySQL ステートメントコメントの紹介

MySQL は次の 3 種類のコメントをサポートしています。 1. 行末の「#」文字から。 2. 「...

Dockerコンテナの原理の分析

目次01 コンテナの本質とは何か? 02 Cgroupテクノロジーと名前空間テクノロジーの概要03 ...

Vueは視覚的なドラッグページエディタを実装します

目次ドラッグアンドドロップの実装ドラッグイベントドラッグして開始リリースゾーンでの移動境界処理、角度...