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 5.7.17 最新インストールチュートリアル(画像とテキスト付き)

mysql-5.7.17-winx64 は MySQL の最新バージョンです。インストールは無料で...

MYSQL における char と varchar の違い

CHAR 型と VARCHAR 型は似ていますが、主に格納場所、末尾のスペース、取得方法が異なります...

Vueはechartsに基づいて3次元の縦棒グラフを実装します

3次元縦棒グラフは、正面、右側、上部の3つの部分で構成されています。描画するときは、正面をグラフィッ...

MySQL 結合バッファの原理

目次1. MySQL 結合バッファ2. JoinBufferCacheストレージスペースの割り当て3...

Dockerは1行のコマンドでFTPサービス構築の実装を完了します

1行のコマンド docker run -d \ -v /share:/home/vsftpd \ -...

Element-ui NavMenuサブメニューを使用して再帰的に生成する場合のエラーの詳細な説明

ナビゲーションバーのサブメニューを再帰的に生成すると、メニューは正常に生成できるが、マウスをホバーす...

MySQLの文字セットと検証ルールの詳細な説明

1いくつかの一般的な文字セットMySQL で最も一般的な文字セットには、ASCII 文字セット、ラテ...

Vue の el-table は自動天井効果を実現します (固定をサポート)

目次序文実装のアイデア効果:使用:メインソースコード:序文多くのケースを見た結果、単純な観点からは、...

64 ビット CentOs7 ソース コードのインストール mysql-5.6.35 プロセス共有

インストールプロセス中に問題が発生しないように、まず依存パッケージをインストールします。 [root...

少なくともn日間連続してログインしているユーザーに対するSQLクエリ

MySQL ツールを使用して、3 日間連続する例を見てみましょう。 1. SQL テーブルを作成しま...

Javascript ツリー メニュー (11 項目)

1. dhtmlxツリー dHTMLxTree は機能豊富なツリー メニュー コントロールです。豊...

jsを使って簡単な計算機を作る

この記事では、jsで簡単な計算機を作成する具体的なコードを参考までに共有します。具体的な内容は次のと...

MySQLはストアドプロシージャを使用して数百万のデータを素早く追加します。サンプルコード

序文インデックスを追加した場合と追加しなかった場合の違いを反映するには、数百万のデータを使用する必要...

forループ内のvarの問題の解決

序文var は ES5 における変数宣言方法です。var で変数を宣言するとループ変数がグローバル変...

Centos7 で keepalived ログを別のパスに設定する方法の詳細な説明

Keepalived のインストール: cd <keepalived_sourcecode_p...