diff --git a/docs/day02/07.md b/docs/day02/07.md index fd069b642..aaf865ca8 100644 --- a/docs/day02/07.md +++ b/docs/day02/07.md @@ -15,7 +15,7 @@ if (age >= 20) { } ``` -2行目の`if (age >= 20) {`の部分に差し掛かると、まずはカッコ内の`age >= 20`が評価されます。この式の値は`false`なので、 +2行目の`if (age >= 20) {`の部分に差し掛かると、まずは括弧内の`age >= 20`が評価されます。この式の値は`false`なので、 ```js if (false) { diff --git a/docs/day02/09.md b/docs/day02/09.md index 48c236888..23fd024fb 100644 --- a/docs/day02/09.md +++ b/docs/day02/09.md @@ -2,7 +2,7 @@ title: 関数 --- -## 純粋な関数 +## 処理の共通化 次のコードを見てください。 @@ -32,7 +32,7 @@ document.write(`
6から18の和は${sum6To18}です。
`); 情報の重複を許さないというルールは**DRY原則**(Don't Repeat Yourself)と呼ばれ、高品質な製品を実現するための基本的な枠組みとなっています。 ::: -## 副作用を持つ関数 +## 純粋な関数 **関数**を用いると、決まった処理をひとまとまりとして扱い、その処理に名前を付けることができます。 @@ -57,6 +57,8 @@ JavaScriptにおける関数は、`function`キーワードから始まる1つ `return`文は、関数の中で到達すると、その時点で関数の実行を中断し、式の評価結果を確定させます。`sum(1, 10)`を実行して`return result;`まで到達したとき、`result`は`55`ですので、式`sum(1, 10)`の評価結果は`55`となります。関数の評価結果を、その関数の**戻り値**と呼びます。 +## 副作用を持つ関数 + 関数は、数学のそれとは異なり、あくまでも処理のまとまりであって、値を返す必要はありません。上のコードは、以下のように書き直すことができます。 ```js diff --git a/docs/day03/01.md b/docs/day03/01.md index e6bc01421..494baf05a 100644 --- a/docs/day03/01.md +++ b/docs/day03/01.md @@ -2,7 +2,7 @@ title: オブジェクト --- -今まで扱ってきたJavaScriptの「値」は、文字列、数値、論理値の3つでした。**オブジェクト**は、複数の値をひとまとまりにして**名前と値のペア**で管理できる、新たな種類の値です。 +今まで扱ってきたJavaScriptの「値」は、文字列、数値、論理値の3つでした。**オブジェクト**は、複数の値をひとまとまりにして**名前と値のペア**で管理できる、新たな種類の値です。また、JavaScriptにおけるオブジェクトではない値を総称して、**プリミティブ**な値といいます。 ## オブジェクトの生成 diff --git a/docs/day03/02.md b/docs/day03/02.md index 8f7202113..f215a240b 100644 --- a/docs/day03/02.md +++ b/docs/day03/02.md @@ -2,6 +2,10 @@ title: 配列 --- +:::note +JavaScriptの配列は、他の言語とかなり異なる性質を持っています。他の言語の経験がある方は注意して読むようにしてください。 +::: + ## 配列の生成 JavaScriptにおける**配列**(Array)は、キーが数値であるオブジェクトです。**配列リテラル**を用いて生成します。 @@ -14,7 +18,7 @@ document.write(myFriends.length); // 3 配列リテラルでは、`[`から`]`までの領域の中に、複数の値をコンマ区切りで記述します。各値には0から始まる整数が自動的にキーとして割り当てられます。キー名が数値となっているため、各要素(プロパティ)にアクセスするためには、ブラケット記法を使用する必要があります。つまり、`myFriends.1`という記法は許されません。 -`['A', 'B', 'C']`のようにして生成された配列は、`{ 0: 'A', 1: 'B', 2: 'C' }`というオブジェクトと似ていますが、異なる点もあります。それが`length`プロパティです。配列には`length`プロパティが自動的に定義され、配列の長さを表します。 +`['A', 'B', 'C']`のようにして生成された配列は、`{ 0: 'A', 1: 'B', 2: 'C' }`というオブジェクトと似ていますが、異なる点もあります。そのひとつが`length`プロパティです。配列には`length`プロパティが自動的に定義され、配列の長さを表します。 ## 配列の要素を列挙する @@ -26,9 +30,9 @@ for (let i = 0; i < myFriends.length; i++) { } ``` -`length`プロパティにより配列の要素数を取得することができるので、それを条件式野中で利用しましょう。 +`length`プロパティにより配列の要素数を取得することができるので、それを条件式の中で利用しましょう。 -`for`文には、配列のようなオブジェクトの要素を列挙するための専用の気泡が存在しています。`for 〜 of`ループです。 +`for`文には、配列のようなオブジェクトの、全ての要素を列挙するための専用の記法が存在しています。`for 〜 of`ループです。 ```js for (const myFriend of myFriends) { @@ -36,7 +40,7 @@ for (const myFriend of myFriends) { } ``` -`for (const 変数 of 配列)`とすることで、配列の各要素を変数に代入しながらループを回すことができます。 +`for (const 変数 of 配列)`とすることで、配列の各要素を変数に代入しながらループを回すことができます。なお、`for 〜 of`ループの中では`const`が使用できることに注意してください。 ## ネストされた配列 diff --git a/docs/day03/04.md b/docs/day03/04.md new file mode 100644 index 000000000..07caaba5e --- /dev/null +++ b/docs/day03/04.md @@ -0,0 +1,107 @@ +--- +title: 関数とオブジェクト +--- + +JavaScriptにおいては、関数も一種のオブジェクトです。関数自体を数値や文字列と同じく通常の値として扱うことができます。 + +:::tip +関数のこのような性質を**第一級関数**と呼びます。 +::: + +## 関数を変数に代入する + +```js +function doSomething() { + document.write('Hello World!'); +} + +const someVariable = doSomething; +someVariable(); +``` + +上の例では、関数`doSomething`を`someVariable`に代入しています。関数が入った変数は、そのまま通常の関数と同様に使用できます。 + +## 関数を関数の引数として使用する + +```js +function callTwice(callback) { + callback(); + callback(); +} + +function sayHello() { + document.write('Hello'); +} + +callTwice(sayHello); +``` + +`callTwice`の内部の`callback`には関数が格納されているので、そのまま実行することができます。 + +## 無名関数 + +**無名関数**とは、名前を持たない関数のことです。**アロー関数式**は、JavaScriptにおいて無名関数を生成する式の一種です。 + +先ほどの例を、無名関数を用いて書き換えてみましょう。 + +```js +callTwice(() => { + document.write('Hello'); +}); +``` + +アロー関数式は、`(引数) => { 処理 }`の形をとります。上記の例では、`() => { document.write('Hello'); }`の部分が、引数を取らず、`Hello`と表示する無名関数を生成する式となっています。 + +## アロー関数式の省略形 + +アロー関数式には、2つの省略記法が存在しています。両方を組み合わせることも可能です。 + +### 引数の括弧の省略 + +アロー関数の引数が1個だけのとき、引数の括弧は省略できます。 + +```js +(x) => { return x * 2; } +``` + +は、 + +```js +x => { return x * 2; } +``` + +のように省略できます。 + +### `return`文とブロックの括弧の省略 + +アロー関数式内が`return`文ただひとつのとき、`return`文と波括弧が省略できます。 + +```js +(x) => { return x * 2; } +``` + +は、 + +```js +(x) => x * 2; +``` + +のように省略できます。 + +## 課題 + +```js +function map1To10(callback) { + const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + for (let i = 0; i < numbers.length; i++) { + numbers[i] = callback(numbers[i]); + } + return numbers; +} +``` + +`map1To10`を適切に呼び出して、以下の戻り値を得てください。 + +```js +[3, 6, 9, 12, 15, 18, 21, 24, 27, 30] +``` diff --git a/docs/day03/05.md b/docs/day03/05.md new file mode 100644 index 000000000..ae579fb90 --- /dev/null +++ b/docs/day03/05.md @@ -0,0 +1,44 @@ +--- +title: イベントハンドラ +--- + +DOM要素に対し、何らかのアクション(**イベント**)が起こった際の反応(**イベントハンドラ**)を定義することができます。 + +```html + +``` + +```js +document.getElementById('amazing-button').onclick = () => { + alert('びっくり!'); +}; +``` + +DOMオブジェクトの`onclick`プロパティには、その要素がクリックされた時に呼ばれる関数を指定します。今回は、アロー関数式を用いて、`() => { alert('びっくり!'); }`という関数を指定しています。 + +:::tip +`alert`は、画面上にモーダルダイアログボックスを表示させる関数です。 +::: + +:::caution +この記事以降、`document.write`は一切使用しません。これは、`document.write`をページの読み込みが完了した状態で実行すると、ページの内容を全て消去してしまうためです。何かを出力する必要がある場合は、代わりに`console.log`を使用しましょう。 +::: + +## イベントオブジェクト + +イベントハンドラには、**イベントオブジェクト**と呼ばれる、起きたイベントの詳細を表すオブジェクトが引数として渡される場合が多いです。イベントオブジェクトを受け取る引数名には、`e`を使う場合が多いです。 + +```html + +``` + +```js +document.querySelector('input').onkeydown = (e) => { + console.log(e.key); +} +``` + +`keydown`イベントのイベントオブジェクトには、押されたキーが格納されている、`key`プロパティがあります。 + +## 課題 +`0`を表示する`div`要素とボタンをひとつ用意し、ボタンがクリックされるたびに`div`要素内部に表示されている値を1ずつ増やすプログラムを作成してください。 diff --git a/docs/day03/06.md b/docs/day03/06.md new file mode 100644 index 000000000..50fef7aca --- /dev/null +++ b/docs/day03/06.md @@ -0,0 +1,41 @@ +--- +title: メソッド +--- + +:::note +この章では、一般的なプログラミング言語におけるメソッドとは若干異なる概念である、JavaScriptのメソッドについて説明します。他のプログラミング言語の経験がある方は注意して読んでください。 +::: + +## メソッドの作成 + +JavaScriptにおいて、関数は一種の値ですので、当然のことながらオブジェクトのプロパティとして使用することもできます。このような関数のことを`メソッド`と呼んでいます。 + +```js +const someObject = { + someMethod: () => { + console.log('Method called'); + }, +}; + +someObject.someMethod(); +``` + +上記の例において、`someMethod`は`someObject`のメソッドである、といいます。 + +:::tip +`console.log`は`console`オブジェクトの`log`メソッドで、`document.write`は`document`オブジェクトの`write`メソッドです。 +::: + +## メソッドの省略記法 + +オブジェクトのメソッドは、次のように記述すると簡単です。 + +```js +const someObject = { + someMethod() { + console.log('Method called'); + } +}; +``` + +以上のコードは、前項のサンプルコードとほとんど同等です。 diff --git a/docs/day03/07.md b/docs/day03/07.md new file mode 100644 index 000000000..6e1dd9b79 --- /dev/null +++ b/docs/day03/07.md @@ -0,0 +1,77 @@ +--- +title: クラスとオブジェクト指向 +--- + +:::info +この記事では、まだJavaScriptの標準仕様には含まれていない[パブリックフィールド宣言](https://github.com/tc39/proposal-class-fields)を使用しています。ChromeとFirefoxでは動作しますが、Safariでは動作しないかもしれません。 +::: + +多くのプログラミング言語が、**オブジェクト指向**という考え方を持っています。オブジェクト指向とは、「データと動作を一つのまとまりとして捉える考え方」です。 + +オブジェクト指向におけるこのまとまりを、**クラス**と呼びます。クラスに含まれるデータが**フィールド**、動作が**メソッド**です。 + +クラスを使うためには、**定義**をしなければなりません。クラスの定義とは、そのクラスがどのようなフィールドやメソッドを持つかを示す、設計図のようなものです。 + +```js +class Dog { + age; + name; + bark() { + if (this.age > 5) { + console.log('バウバウ'); + } else { + console.log('ワンワン'); + } + } +} +``` + +JavaScriptにおいてクラスを定義するためには、`class`構文を用います。上の例で示した`Dog`クラスの定義は、現実世界の犬を表す設計図です。犬を表すためのデータには、例えば「年齢」や「名前」があります。これが`age`フィールドや`name`フィールドです。 + +犬に関わる動作には、例えば「吠える」などがあります。`bark`メソッドとしてみましょう。メソッドの中の`this`キーワードは、設計図から生まれた実体を表します。 + +```js +const pochi = new Dog(); +pochi.name = 'ポチ'; +pochi.age = 8; +pochi.bark(); +``` + +`Dog`の定義から実体(**インスタンス**)を作り出すためには、`new`キーワードを用います。インスタンスは通常のJavaScriptオブジェクトと同様の形式なので、ドット記法またはブラケット記法によりフィールドやメソッドにアクセスできます。 + +`pochi.bark();`を実行した際、`bark`メソッド内で得られる`this`は`pochi`そのものです。この仕組みにより、クラス定義は、全てのインスタンスで共通する動作を問題なく抽象化できます。 + +なお、これ以降、クラスのメソッドは`#`記号を用いて表すこととします。例えば、`Dog`クラスの`bark`メソッドは`Dog#bark`メソッドと表記します。 + +## コンストラクタ + +コンストラクタは、`new`演算子が使用された際に呼び出される関数です。`JavaScript`では、`constructor`という名前のメソッドを定義することで使用することができます。 + +```js +class Dog { + age; + constructor(age) { + this.age = age; + } +} + +const pochi = new Dog(8); +console.log(pochi.age); // 8 +``` + +コンストラクタは、他の関数と同じように、引数を取ることができます。通常、コンストラクタに渡される値は、フィールドの初期化などに用いられます。 + +## コンストラクタを使用する + +JavaScriptには、日時を表すための`Date`クラスが用意されています。`Date`クラスのコンストラクタは、例えば文字列引数1つにより呼び出すことができ、その文字列を日付として解釈しようと試みます。`Date`クラスには、日時を扱うための様々な便利メソッドが用意されています。 + +```js +const valentinesDay = new Date('2020-02-14 00:00:00'); +console.log(valentinesDay.getDate()); // 14 +``` + +例えば、`Date#getDate`メソッドは、その日の日付を返すメソッドです。 + +## 課題 + +`Dog`クラスに、`私の名前は〜です。`(〜の部分に`name`プロパティを埋め込む)とコンソールに出力する`introduceSelf`メソッドを追加してください。実際に`introduceSelf`メソッドを実行させ、正常に動作することを確認してください。 diff --git a/docs/day03/08.md b/docs/day03/08.md new file mode 100644 index 000000000..039af65c1 --- /dev/null +++ b/docs/day03/08.md @@ -0,0 +1,67 @@ +--- +title: 組み込みクラス +--- + +## Arrayクラス + +今まで何気なく扱ってきたJavaScriptの配列ですが、実は`Array`クラスのインスタンスです。具体的に言えば、配列リテラルが生成するオブジェクトは、`Array`クラスのインスタンスです。 + +Arrayクラスには、開発効率を劇的に変える便利なメソッドが大量に定義されています。 + +### `map`メソッド + +`Array#map`メソッドは、関数の引数をひとつとり、配列の各要素に対して関数を実行し、それらの戻り値からなる新たな配列を返します。 + +```js +const numbers = [1, 3, 6, 8]; +const doubledNumbers = numbers.map(value => value * 2); // [2, 6, 12, 16] +``` + +2行目の`map`メソッドの引数として渡しているアロー関数式`value => value * 2`は、引数をひとつとり、その値を2倍にして返す関数です。この関数が配列の各要素に対して実行されて、その戻り値の集合が`doubledNumber`となっています。 + +### `filter`メソッド + +`Array#filter`メソッドは、関数の引数をひとつとり、配列の各要素に対して関数を実行し、それらの戻り値がtruthyだったもののみからなる新しい配列を返します。 + +```js +const evenNumbers = numbers.filter(value => value % 2 === 0); // [6, 8] +``` + +アロー関数式`value => value % 2 === 0`は、引数が偶数の場合`false`を、奇数の場合`true`を返す関数です。`numbers`のうち`6`と`8`の場合のみ戻り値が`true`となるので、その2つのみからなる新しい配列が`evenNumbers`に入ります。 + +## DOMオブジェクトと継承 + +DOMオブジェクトも、何らかのクラスのインスタンスだとみなせます。例えば、 + +```js +document.querySelector('div'); +``` + +のようにして取得された`div`要素は、`HTMLDivElement`クラスのインスタンスだと考えられます。 + +[`HTMLDivElement`について記述している文書](https://developer.mozilla.org/ja/docs/Web/API/HTMLDivElement)を読んでみましょう。おなじみ`textContent`プロパティや`style`プロパティが存在していませんね。 + +これには、**継承**と呼ばれる仕組みが関係しています。継承とは、その名の通り機能を受け継ぐための仕組みです。ここでいう機能とは、例えばプロパティやメソッドです。継承先のオブジェクトでは、継承元のプロパティやメソッドを使用することができます。 + +DOMは非常に高度な枠組みです。今回の例でいえば、`HTMLDivElement`は`HTMLElement`を継承しており、`HTMLElement`は`Element`を、そして`Element`は`Node`を継承しています。そして`HTMLDivElement`は、そのすべてを利用できるのです。 + +実は、`textContent`は`Node`オブジェクトのプロパティで、`style`は`HTMLElement`オブジェクトのプロパティです。どのプロパティがどのオブジェクトに所属するのかを具体的に記憶する必要性はあまりありませんが、リファレンスを調べる場合にこの知識は大変有用です。 + +## 課題 + +[`Array#reduce`メソッド](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)は、配列のすべての要素から、単一の値を導き出す(次元を下げる)メソッドです。 + +```js +const sum = [1, 2, 3, 4, 5].reduce((previous, current) => previous + current, 0); +console.log(sum); // 15 +``` + +`reduce`メソッドの第一引数は、引数を2つとる関数です。配列の各要素をこの関数の第二引数に渡し、戻り値を次の実行時に第一引数として渡します。この第一引数は、初回実行時には`reduce`メソッド自体の第二引数が用いられます(ただしこの引数が省略された場合は配列の最初の要素が用いられ、実行回数が1回分減ります)。 + +`reduce`メソッドを使用して、配列の最小値を求めてみてください。 + +```js +const numbers = [6, 9, 1, 3, 2]; +const minimumNumber = numbers.reduce(/** ここに記述 */); +console.log(minimumNumber); // 1 +``` diff --git a/docs/day03/09.md b/docs/day03/09.md new file mode 100644 index 000000000..2213f37ad --- /dev/null +++ b/docs/day03/09.md @@ -0,0 +1,101 @@ +--- +title: プルリクエストを用いた共同開発 +--- + +GitHubには、**プルリクエスト**と呼ばれる、変更を提案するための機能があります。この機能を正しく利用することで、複数人による開発を円滑に進めることができます。 + +## ブランチ + +以前少し触れたとおりGitにおける**ブランチ**とは、ソースコードの分岐です。複数人で開発をする場合は、同じソースコードに複数人が同時に触れることのないよう、編集を枝分かれさせます。 + + + +作業しているブランチを切り替えるためには、`git checkout`コマンドを使用します。ただし、ブランチがまだ存在せず、新しく作成することが必要な場合は`-b`オプションを付けます。 + +複数のブランチをひとつのブランチに統合する作業を**マージ**といいます。分岐したブランチでいくつかのコミットをしたら、もとのブランチをチェックアウトした状態で`git merge`コマンドを実行しましょう。**マージコミット**が作成され、分岐先のブランチの変更を取り込むことができます。 + +## プルリクエストを利用してマージする + +Gitのリポジトリを作成すると、通常`master`ブランチが作成されます。`master`ブランチは、すべての起点となる重要なブランチです。このため、`master`ブランチへのマージ作業は慎重に行うべきでしょう。GitHubのプルリクエスト機能を使用すれば、マージ前に様々な確認作業を行うことができます。 + +まずは、**トピックブランチ**(あるひとつの変更を加えるためのブランチ)を作成します。どのような変更を行うかを把握しやすいネーミングを心がけましょう。 + +``` +$ git checkout -b add-something +``` + +続いて、トピックブランチ上で適当な編集を行い、コミットします。 + +``` +$ git add -A +$ git commit -m "somethingを追加した" +``` + +リモートリポジトリにプッシュしましょう。 + +``` +$ git push -u origin add-something +``` + +:::tip +`git checkout`コマンドで作成したブランチは、まだローカルリポジトリにしか存在していないため、プッシュする際に`-u`オプションを指定して、リモートリポジトリを指定する必要があります。2回目以降のプッシュでは`git push`のみで構いません。 +::: + +続いて、GitHubの`Pull requests`タブから、`New pull request`もしくは`New`をクリックします。 + + + +`base`をマージ先のブランチ、`compare`を先ほど作成したブランチに設定し、プルリクエストのタイトルとメッセージを記入します。 + +:::tip +先ほどの画面で`Compare & pull request`のボタンが表示されていた場合は自動的に`base`と`compare`が設定されます。 +::: + + + +`Create pull request`を選択すると、プルリクエストが作成されます。 + + + +`Merge pull request`を押して確認すれば、変更が`base`に指定したブランチに反映されます。 + +``` +$ git checkout master +$ git pull +``` + +`master`ブランチをプルして、変更が正しく反映されていることを確認しましょう。 + +## ほかの人のリポジトリの開発に参加する + +### 権限の付与 + +`Settings`の`Manage access`から、`Invite a collaborator`を押すことで、ほかの人をリポジトリに招待することができます。 + + + +### 開発の開始 + +権限が付与されると、メールでその旨が通知されます。リポジトリの`Code`ボタンからリポジトリのURLを取得し + +``` +$ git clone [リポジトリのURL] +``` + +としてリモートリポジトリをクローンしましょう。 + + + +:::tip +`git clone`を用いてリポジトリをクローンした場合には、はじめからリモートリポジトリが結びついているため、 + +``` +$ git remote add origin [リポジトリのURL] +``` + +を実行する必要はありません。 +::: + +## 課題 + +ut.code(); Learn(このウェブサイト)は、[GitHubにて管理](https://github.com/ut-code/utcode-learn)されています。編集権限を受け取り、何かしらの編集をして、プルリクエストを作成してみましょう。 diff --git a/docs/day03/09/authorize-others.png b/docs/day03/09/authorize-others.png new file mode 100644 index 000000000..4ca75c3e5 Binary files /dev/null and b/docs/day03/09/authorize-others.png differ diff --git a/docs/day03/09/branch.svg b/docs/day03/09/branch.svg new file mode 100644 index 000000000..118044659 --- /dev/null +++ b/docs/day03/09/branch.svg @@ -0,0 +1,68 @@ + diff --git a/docs/day03/09/clone-repository.png b/docs/day03/09/clone-repository.png new file mode 100644 index 000000000..061d3d9b8 Binary files /dev/null and b/docs/day03/09/clone-repository.png differ diff --git a/docs/day03/09/fork.png b/docs/day03/09/fork.png new file mode 100644 index 000000000..000b6c1b8 Binary files /dev/null and b/docs/day03/09/fork.png differ diff --git a/docs/day03/09/new-pull-request-preparation.png b/docs/day03/09/new-pull-request-preparation.png new file mode 100644 index 000000000..e2f724d9a Binary files /dev/null and b/docs/day03/09/new-pull-request-preparation.png differ diff --git a/docs/day03/09/new-pull-request.png b/docs/day03/09/new-pull-request.png new file mode 100644 index 000000000..ac0f960c9 Binary files /dev/null and b/docs/day03/09/new-pull-request.png differ diff --git a/docs/day03/09/pull-request-created.png b/docs/day03/09/pull-request-created.png new file mode 100644 index 000000000..641abf704 Binary files /dev/null and b/docs/day03/09/pull-request-created.png differ diff --git a/docs/day03/10.md b/docs/day03/10.md new file mode 100644 index 000000000..98e96ac03 --- /dev/null +++ b/docs/day03/10.md @@ -0,0 +1,7 @@ +--- +title: "課題: フロントエンドの総まとめ" +--- + +電卓アプリを作成してみましょう。DRY原則に忠実に実装できますか? + + diff --git a/docs/day03/10/calc.png b/docs/day03/10/calc.png new file mode 100644 index 000000000..0c1e51942 Binary files /dev/null and b/docs/day03/10/calc.png differ