1.値と参照を格納する変数
JavaScriptで変数値がどのように正確に割り当てられるかを理解することは、正しく機能するコードを作成する人にとって非常に重要です。 このメカニズムを誤解すると、変数の値が誤って変更される可能性のあるプログラムを作成することになります。
JavaScriptは、エンティティにプリミティブ型(特に
Boolean
、
null
、
undefined
、
String
および
Number
型)のいずれかがある場合、常にこのエンティティの値を使用します。 つまり、値は対応する変数に書き込まれます。 オブジェクト(
Object
、
Array
、
Function
タイプなど)について話している場合、変数に割り当てると、その参照がメモリにあるアドレスに書き込まれます。
例を考えてみましょう。 次のコードスニペットでは、文字列が
var1
変数に書き込まれます。 その後、
var2
の値が
var2
変数に書き込まれます。
var1
にはプリミティブ型(
String
)があるため、
var1
の文字列のコピーが
var1
に書き込まれ
var1
。 これにより、
var2
は
var1
と完全に独立した変数と
var2
ことができますが、
var1
と同じ値を格納します。
var1
新しい値を
var1
も
var1
は影響しません。
let var1 = 'My string'; let var2 = var1; var2 = 'My new string'; console.log(var1); // 'My string' console.log(var2); // 'My new string'
次に、オブジェクトを操作する例を考えてみましょう。
let var1 = { name: 'Jim' } let var2 = var1; var2.name = 'John'; console.log(var1); // { name: 'John' } console.log(var2); // { name: 'John' }
ご覧のとおり、ここでは
var2
変数を使用していますが、同じオブジェクトへの参照を保存しているため、
var1
変数に反映されます。 オブジェクトを保存する変数がプリミティブ型の値を保存する変数と同じように振る舞うと誰かが判断した場合、実際のコードでこれが何につながるか想像するのは簡単です。 これは、たとえば、渡されたオブジェクト値で動作するように設計された関数を作成し、この関数が誤ってこの値を変更する場合など、特に不快です。
2.短絡
クロージングは、変数を使用して保護された作業を整理できるようにするJavaScriptの重要なデザインパターンです。 次の例では、
createGreeter()
関数は、文字列
Hello
を含む
greeting
引数とともに提供される元の引数にアクセスできる匿名関数を返します。 この匿名関数への参照は、
sayHello
変数に書き込まれます。 その後、
sayHello()
関数を何度呼び出しても、常に
greeting
値にアクセスできます。 この場合、
greeting
へのアクセスは匿名関数のみで、そのリンクは
sayHello
記録されます。
function createGreeter(greeting) { return function(name) { console.log(greeting + ', ' + name); } } const sayHello = createGreeter('Hello'); sayHello('Joe'); // Hello, Joe
これは非常に簡単な例です。 現実の世界に近いものを見ると、たとえば、特定のAPIに接続するための関数(
apiConnect()
と呼びましょう
apiConnect()
できます。最初に呼び出されたときにAPIアクセスキーが渡されます。 次に、この関数は、
apiConnect()
渡されるAPIアクセスキーを使用するいくつかのメソッドを含むオブジェクトを返します。 この場合、キーはクロージャーに保存され、これらのメソッドを呼び出すときに、キーを記述する必要はなくなりました。
function apiConnect(apiKey) { function get(route) { return fetch(`${route}?key=${apiKey}`); } function post(route, params) { return fetch(route, { method: 'POST', body: JSON.stringify(params), headers: { 'Authorization': `Bearer ${apiKey}` } }) } return { get, post } } const api = apiConnect('my-secret-key'); // API api.get('http://www.example.com/get-endpoint'); api.post('http://www.example.com/post-endpoint', { name: 'Joe' });
3.破壊的な割り当て
JavaScriptで破壊的な割り当てをまだ使用していない場合は、修正する時が来ました。 破壊的な割り当ては、きちんとした構文言語構造を使用してオブジェクトプロパティを取得する一般的な方法です。
const obj = { name: 'Joe', food: 'cake' } const { name, food } = obj; console.log(name, food); // 'Joe' 'cake'
オブジェクトに含まれているものとは異なる抽出されたプロパティ名を割り当てる必要がある場合、これを行うことができます。
const obj = { name: 'Joe', food: 'cake' } const { name: myName, food: myFood } = obj; console.log(myName, myFood); // 'Joe' 'cake'
次の例では、デストラクタリングを使用して、
person
オブジェクトのプロパティに格納されている値を、
introduce()
関数に正確に渡します。 これは、渡されたパラメーターを持つオブジェクトからデータを取得する関数を宣言するときに、この構造がどのように使用されるかの例です。 ところで、Reactに精通しているのであれば、おそらくすでにこれを見たことがあるでしょう。
const person = { name: 'Eddie', age: 24 } function introduce({ name, age }) { console.log(`I'm ${name} and I'm ${age} years old!`); } console.log(introduce(person)); // "I'm Eddie and I'm 24 years old!"
4.スプレッド演算子
スプレッド演算子は、準備ができていない人には理解できないと思われるかなり単純な構造です。 次の例には、数値配列があり、最大値が格納されています。 これには
Math.max()
メソッドを使用しますが、
Math.max()
方法がわかりません。 彼は、引数として、独立した数値を想定しています。 配列から要素を抽出するために、3つのポイントのように見えるスプレッド演算子を使用します。
const arr = [4, 6, -1, 3, 10, 4]; const max = Math.max(...arr); console.log(max); // 10
5.残りのステートメント
restステートメントを使用すると、関数に渡された任意の数の引数を配列に変換できます。
function myFunc(...args) { console.log(args[0] + args[1]); } myFunc(1, 2, 3, 4); // 3
6.配列メソッド
配列メソッドは、多くの場合、さまざまなデータ変換タスクを美しく解決できる便利なツールを開発者に提供します。 StackOverflowに関する質問に時々答えます。 その中には、オブジェクトの配列を操作するこれらの方法または他の方法に専念しているものがよくあります。 このような状況では、配列メソッドが特に役立ちます。
ここでは、これらの方法のいくつかを検討します。これらの方法は、互いに類似しているという原則に基づいています。 ここで、配列のすべての方法について説明するわけではないことに注意してください。 MDNで完全なリストを見つけることができます(ちなみに、これは私のお気に入りのJavaScriptリファレンスです)。
▍Map()、filter()、reduce()メソッド
map()
、
filter()
および
reduce()
配列メソッドを使用すると、配列を変換したり、配列を単一の値(オブジェクトにすることができます)にしたりできます。
map()
メソッドは、処理された配列の変換された値を含む新しい配列を返します。 どのように正確に変換されるかは、このメソッドに渡される関数で指定されます。
const arr = [1, 2, 3, 4, 5, 6]; const mapped = arr.map(el => el + 20); console.log(mapped); // [21, 22, 23, 24, 25, 26]
filter()
メソッドは要素の配列を返し、このメソッドに渡された関数が
true
返した値を確認します。
const arr = [1, 2, 3, 4, 5, 6]; const filtered = arr.filter(el => el === 2 || el === 4); console.log(filtered); // [2, 4]
reduce()
メソッドは、配列のすべての要素を処理した結果である特定の値を返します。
const arr = [1, 2, 3, 4, 5, 6]; const reduced = arr.reduce((total, current) => total + current); console.log(reduced); // 21
▍メソッドfind()、findIndex()およびindexOf()
配列メソッド
find()
、
findIndex()
および
indexOf()
、混同しやすいものです。 以下は、機能の理解に役立つ説明です。
find()
メソッドは、指定された基準に一致する配列の最初の要素を返します。 最初の適切な要素を見つけるこのメソッドは、配列内の検索を続行しません。
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const found = arr.find(el => el > 5); console.log(found); // 6
この例では、数値5を含む配列要素に続くすべての配列要素が指定された基準に対応しますが、最初の適切な要素のみが返されることに注意してください。 このメソッドは、forループを使用して配列を列挙および分析する場合に、
break
ステートメントを使用して、配列内に目的の要素が見つかったときにそのようなループが中断される状況で非常に役立ちます。
findIndex()
メソッドは
find()
に非常に似てい
find()
が、配列内の最初の適切な要素を返す代わりに、その要素のインデックスを返します。 この方法をよりよく理解するために、文字列値の配列を使用する次の例を見てください。
const arr = ['Nick', 'Frank', 'Joe', 'Frank']; const foundIndex = arr.findIndex(el => el === 'Frank'); console.log(foundIndex); // 1
indexOf()
メソッドは
findIndex()
indexOf()
メソッドと非常に似ていますが、関数ではなく通常の値を引数として取ります。 目的の配列要素を検索するときに複雑なロジックが必要ない場合に使用できます。
const arr = ['Nick', 'Frank', 'Joe', 'Frank']; const foundIndex = arr.indexOf('Frank'); console.log(foundIndex); // 1
▍Push()、pop()、shift()、およびunshift()メソッド
push()
、
pop()
、
shift()
および
unshift()
を使用して、新しい要素を配列に追加し、それらにすでに存在する要素を配列から抽出します。 この場合、作業は配列の先頭または末尾にある要素で実行されます。
push()
メソッドを使用すると、配列の末尾に要素を追加できます。 配列を変更し、完了すると、配列に追加された要素を返します。
let arr = [1, 2, 3, 4]; const pushed = arr.push(5); console.log(arr); // [1, 2, 3, 4, 5] console.log(pushed); // 5
pop()
メソッドは、配列から最後の要素を削除します。 配列を変更し、そこから削除された要素を返します。
let arr = [1, 2, 3, 4]; const popped = arr.pop(); console.log(arr); // [1, 2, 3] console.log(popped); // 4
shift()
メソッドは、配列から最初の要素を削除して返します。 また、呼び出される配列を変更します。
let arr = [1, 2, 3, 4]; const shifted = arr.shift(); console.log(arr); // [2, 3, 4] console.log(shifted); // 1
unshift()
メソッドは、配列の先頭に1つ以上の要素を追加します。 彼は再び、配列を変更します。 同時に、ここで説明した他の3つのメソッドとは異なり、配列の新しい長さを返します。
let arr = [1, 2, 3, 4]; const unshifted = arr.unshift(5, 6, 7); console.log(arr); // [5, 6, 7, 1, 2, 3, 4] console.log(unshifted); // 7
▍メソッドslice()およびsplice()
これらのメソッドは、配列を変更したり、配列の一部を返すために使用されます。
splice()
メソッドは、既存の要素を削除するか、他の要素に置き換えることにより、配列の内容を変更します。 彼は配列に新しい要素を追加することができます。 このメソッドは配列を変更します。
次の例は、通常の言語で記述した場合、次のようになります。配列位置
1
で、
0
要素を削除し、
b
を含む要素を追加する必要があります。
let arr = ['a', 'c', 'd', 'e']; arr.splice(1, 0, 'b')
slice()
メソッドは、指定された開始位置から始まり、指定された終了位置の前の位置で終わる、要素を含む配列の浅いコピーを返します。 呼び出し時に初期位置のみが指定されている場合、この位置から開始して配列全体を返します。 このメソッドは配列を変更しません。 呼び出されたときに記述されたこの配列の一部のみを返します。
let arr = ['a', 'b', 'c', 'd', 'e']; const sliced = arr.slice(2, 4); console.log(sliced); // ['c', 'd'] console.log(arr); // ['a', 'b', 'c', 'd', 'e']
▍メソッドsort()
sort()
メソッドは、渡された関数で指定された条件に従って配列をソートします。 この関数は、配列の2つの要素(たとえば、パラメーター
a
および
b
として表すことができます)を受け取り、それらを比較して、要素を交換する必要がない場合、0よりも低いインデックスに配置
a
必要がある場合
a
0を返します
b
は負の数であり、
b
よりも低いインデックスに配置する必要がある場合は、正の数です。
let arr = [1, 7, 3, -1, 5, 7, 2]; const sorter = (firstEl, secondEl) => firstEl - secondEl; arr.sort(sorter); console.log(arr); // [-1, 1, 2, 3, 5, 7, 7]
これらの方法を初めて思い出せない場合は、覚えておいても大丈夫です。 最も重要なことは、標準の配列メソッドで何ができるかについて今知っていることです。 したがって、特定のメソッドの機能をすぐに思い出せない場合、そのメソッドについて知っていることで、ドキュメントで必要なものをすばやく見つけることができます。
7.ジェネレーター
JavaScriptジェネレーターは、アスタリスク文字を使用して宣言されます。
next()
メソッドが呼び出されたときに返される値を指定できます。 ジェネレーターは、限られた数の値を返すように設計できます。 そのようなジェネレータがそのような値をすべて返した場合、
next()
次の呼び出しは
undefined
を返します。 サイクルを使用して無制限の数の値を返すように設計されたジェネレーターを作成することもできます。
以下は、限られた数の値を返すように設計されたジェネレーターです。
function* greeter() { yield 'Hi'; yield 'How are you?'; yield 'Bye'; } const greet = greeter(); console.log(greet.next().value); // 'Hi' console.log(greet.next().value); // 'How are you?' console.log(greet.next().value); // 'Bye' console.log(greet.next().value); // undefined
そして、ループを通して無限の値を返すように設計されたジェネレーターがあります。
function* idCreator() { let i = 0; while (true) yield i++; } const ids = idCreator(); console.log(ids.next().value); // 0 console.log(ids.next().value); // 1 console.log(ids.next().value); // 2 // ...
8.値の等価性(==)および厳密な等価性(===)をチェックするための演算子
JS開発者にとって、等価(
==
)演算子と厳密な等価(
===
)演算子の違いを理解することは非常に重要です。 事実は、値を比較する前に演算子
==
が型の変換を実行し(一見すると奇妙な結果につながる可能性があります)、演算子
===
は型変換を実行しません。
console.log(0 == '0'); // true console.log(0 === '0'); // false
9.オブジェクトの比較
私は時折、JSプログラミングの初心者が同じ間違いをする方法を確認する必要があります。 オブジェクトを直接比較しようとします。 オブジェクトが「格納される」変数には、これらのオブジェクト自体ではなく、それらへの参照が含まれます。
たとえば、次の例では、オブジェクトは同じように見えますが、直接比較すると、各変数には独自のオブジェクトへのリンクが含まれており、これらのリンクは互いに等しくないため、オブジェクトが異なることがわかります。
const joe1 = { name: 'Joe' }; const joe2 = { name: 'Joe' }; console.log(joe1 === joe2); // false
さらに、次の例では、両方の変数が同じオブジェクトへの参照を格納しているため、
joe1
は
joe1
と等しいことが
joe2
ます。
const joe1 = { name: 'Joe' }; const joe2 = joe1; console.log(joe1 === joe2); // true
実際のオブジェクト比較の方法の1つは、JSON文字列形式への予備変換です。 確かに、このアプローチには1つの問題があります。オブジェクトの結果の文字列表現では、プロパティの特定の順序が保証されないということです。 オブジェクトを比較するより信頼性の高い方法は、オブジェクトの詳細な比較のためのツールを含む特別なライブラリを使用することです(たとえば、これはlodashライブラリのisEqual()メソッドです)。
オブジェクトを比較することの複雑さをよりよく理解し、異なる変数で同じオブジェクトへのリンクを書くことの考えられる結果を理解するために、この記事で説明した最初のJSコンセプトを見てください。
10.コールバック関数
コールバック関数は、初心者には難しい場合があるかなり単純なJavaScriptの概念です。 次の例を考えてみましょう。 ここで、
console.log
関数(そのように—括弧なし)は、コールバック関数として
myFunc()
渡されます。 この関数はタイマーを設定し、その後
console.log()
が呼び出され、
myFunc()
渡された文字列がコンソールに表示されます。
function myFunc(text, callback) { setTimeout(function() { callback(text); }, 2000); } myFunc('Hello world!', console.log); // 'Hello world!'
11.約束
コールバック関数を学習し、あらゆる場所で使用を開始すると、すぐにいわゆる「コールバック地獄」に陥ります。 あなたが本当にそこにいるなら-約束を見てみましょう。 非同期コードはプロミスにラップすることができ、実行が成功した後、適切なメソッドを呼び出してプロミスの正常な解決をシステムに伝え、何か問題が発生した場合は、これを示すメソッドを呼び出してプロミスを拒否します。 promiseによって返された結果を処理するには、
then()
メソッドを使用し、エラー処理には
catch()
メソッドを使用します。
const myPromise = new Promise(function(res, rej) { setTimeout(function(){ if (Math.random() < 0.9) { return res('Hooray!'); } return rej('Oh no!'); }, 1000); }); myPromise .then(function(data) { console.log('Success: ' + data); }) .catch(function(err) { console.log('Error: ' + err); }); // Math.random() , , 0.9, : // "Success: Hooray!" // Math.random() , , 0.9, 0.9, : // "Error: On no!"
12. async / awaitコンストラクト
約束を処理した後、おそらく、さらに何かが必要になります。 たとえば、async / awaitコンストラクトをマスターします。 それは約束のための構文糖衣です。 次の例では、
async
を使用して非同期関数を作成し、その中で
await
キーワードを使用し
await
、greeter
greeter
するまで待機
greeter
ます。
const greeter = new Promise((res, rej) => { setTimeout(() => res('Hello world!'), 2000); }) async function myFunc() { const greeting = await greeter; console.log(greeting); } myFunc(); // 'Hello world!'
まとめ
前にここで話したことがあなたに馴染みのないものであれば、おそらく少なくとも少しですが、この記事を読んで自分より上に成長した可能性が高いでしょう。 ここで新しいものを見つけていない場合は、この資料がJavaScriptの知識を実践および強化する機会を与えてくれることを願っています。
親愛なる読者! この記事に追加する他のJavaScriptの概念は何ですか?