最前提として、私はHTML/CSSとかの延長でJavascriptを書いたことがあるが、
プログラミングとしてはきちんと勉強してこなかったので復習としてまとめておく
(今後、TypescriptとReactを学ぶための基本として、かつ、pythonやPHPと同じくpaizaを今後やっていくため)
都度追記します。できたところまで公開。
1.基本の書き方
基本は上から順番に実行される
functionとかで囲まなくてOK
// Hello,Worldと出力
alert("Hello, world")
javaなどで見られる、functionで囲む書き方もできるが
そうするとあとからそれを呼び出す必要がある
処理を分けたいときとか、再度実行させるときとか、イベントで実行させたいとき
とかに使う。
そうでないならそのまま書けばOK
function main() {
alert("Hello, World!");
}
// これ書かないと何も起こらない
main();
2. 変数とデータ型
前主流だったvar
は基本使わず、let
かconst
を使う
ちなみにvarは関数スコープだったが、
letやconstはブロックスコープであることに注意
変数の種類
const
一度代入した値を変更できない、いわゆる定数。迷ったらこれを使う
値を変更する必要があればletに変更、と覚えておけばOK
const name = "Taro";
console.log(name); // OK
name = "Jiro"; // エラー!const で再代入はNG
let
値の再代入が可能。ループや状態変更に使う
let count = 1;
count = 5; // OK
console.log(count); // 5
var
一応あるが全く使わないようにしたい。
なのでここではコードを書かない。
データ型
JSは動的型付け言語なので、変数を宣言するときに型を指定しない。
が、内部にはちゃんと型がある。
ちなみにデータ型を調べるにはtypeof
を使う
typeof (変数) というふうに使えばOK
let x = 123;
console.log(typeof x); // "number"
let y = "Hello";
console.log(typeof y); // "string"
プリミティブ型
-
string
例)"Hello"、'World' -
number
例)123, 3.14, -42, NaN, Infinity -
boolean
例)true, false -
undefined
例)let x; の状態 -
null
例)明示的な「空」 -
bigint
例)12345678901234567890n(n が必要) -
symbol
例)Symbol("id")
※ string型では テンプレート文字列が使える
${}で囲んだところは変数をいれると変換してくれる。
pythonでも似たようなのがある
let name = "Taro";
let message = `Hello, ${name}`; // テンプレート文字列
- NaNは計算不能という数値型、Infinityは無限大という数値型
文字列でも数値型ということ
※ Symbol型は **「一意な値(=誰ともかぶらない値)」**を作るために使われる特別なデータ型
オブジェクトの隠しキーやライブラリ内部などで重宝する
参照型
-
object
配列とか関数とか
let fruits = ["apple", "banana"];
console.log(typeof fruits); // "object"
function greet() {
return "Hello";
}
console.log(typeof greet); // "function"
//ちなみにnullをtypeofすると
console.log(typeof null) //Objectが返る。有名なバグだが今も修正されていない
※TypeScript(TS)だと、明示的に型を書くようになる
詳しくは別記事にかく予定
let name: string = "Taro";
let age: number = 20;
let isAdmin: boolean = true;
オブジェクトについて詳しく
- キーと値のペアで情報をまとめる箱
- 何でも入れられる(文字列・数値・関数・配列・他のオブジェクト)
- ドット記法 or 角括弧記法でアクセス
- JavaScriptでは超重要なデータ構造!
学ぶことを調べていく中で個人的に知らなかった書き方を見つけたので
この際にまとめておく
オブジェクトの中にメソッドを入れられるというのが驚きだった
配列(Array)は番号でアクセスするが、
オブジェクト(Object)はキーでアクセス
ループのfor文でのアクセス方法にも違いがある
配列はfor
...of
、オブジェクトはfor
...in
/ Object.keys()
//オブジェクトの基本形
const person = {
name: "Taro",
age: 20,
isStudent: true
};
//コール方法
console.log(person.name); // → "Taro"
console.log(person["age"]); // → 20
//追加
person.country = "Japan"; // 新しいキーを追加
person.age = 21;// 値を上書き
//削除
delete person.isStudent;
//オブジェクトの中にメソッドを持てる
const person = {
name: "Taro",
greet: function() {
console.log("Hi, I'm " + this.name);
}
};
person.greet(); // → Hi, I'm Taro
3. 関数
基本の書き方
ここはかわってない、function
で定義
phpに似た書き方
function greet(name) {
return "Hello, " + name;
}
アロー関数
functionを使わない書き方。
昔の無名関数の書き方と似ている。
値として扱いやすい。
実質、コールバックとかイベントとかで使えそう。
試しに上の関数をアロー関数で書くと
const greet = (name) => {
return "Hello, " + name;
}
//もっと簡単に書ける
const greet = name => "Hello, " + name;
変わったところ
- function →
const
-
()
の前に=
、後ろに=>
- 引数が1つなら
()
を省略できる - 本文が1行なら
{}
もreturn
も省略可
★何度も上のJSから書いて覚えると良い
cf)昔の無名関数の書き方
ビミョーによく似ている
const greet = function(name) {
return "Hello, " + name;
};
アロー関数とfunctionのThisの挙動の違い
結論:Thisを使うならアローではなくfunctionを使うこと
const obj = {
name: "Taro",
// 通常の function
sayHello: function () {
console.log("Hello from", this.name);
},
// アロー関数
sayHi: () => {
console.log("Hi from", this.name);
}
};
obj.sayHello(); // → Hello from Taro
obj.sayHi(); // → Hi from undefined
sayHello() は呼び出されたときに this = objと考える
sayHi は作られたときの this を記憶 → グローバルの this を使ってしまう
そのためFunctionを使うのが良い
4.配列
phpやPythonなどとよく似ているのでさらっと
//基本形
const fruits = ["apple","banana","orange"];
console.log(fruits[0]); //要素取得
fruits[1] = "grape"; //要素変更
fruits.push("peach") //要素追加(末尾)
fruits.pop() //要素削除(末尾)
fruits.unshift("melon") //要素追加(先頭)
fruits.shift() //要素削除(先頭)
console.log(fruits.length) //要素数取得
//配列ループ処理(昔なつかし)
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
//今はこれがモダン
for (const fruit of fruits) {
console.log(fruit);
}
//または関数型
fruits.forEach((fruit, index) => {
console.log(index, fruit);
});
// ちなみにデータ型がバラバラでも格納できる
const mixed = [
"apple", // 文字列
42, // 数値
true, // 真偽値
{ name: "Taro" }, // オブジェクト
[1, 2, 3], // 配列(ネスト)
function () {
console.log("Hello");
}, // 関数
null, // null
undefined // undefined
];
よく使う配列メソッドたち
よその言語で見たことがあるものもちらほら
map()
filter()
find()
includes()
some()
every()
reduce()
nums.map(n => n * 2) // 各要素を加工して新配列
nums.filter(n => n > 0) // 条件に合う要素を抽出
nums.find(n => n > 5) // 最初に一致した1件だけ取得
fruits.includes("apple") // 値があるか調べる
nums.some(n => n > 10) // 一部が条件を満たすか
nums.every(n => n > 0) // 全部が条件を満たすか
nums.reduce((a,b)=>a+b, 0) // 値をまとめて一つにする
便利な構文
pythonやPHPで見るやつ
スプレッド構文
const fruits = ["apple","banana","orange"];
const moreFruits = [...fruits, "peach"];
分散代入
const fruits = ["apple","banana","orange"];
const [first, second] = fruits;
console.log(first); // "apple"
オブジェクトとの違い
上でも紹介したけど改めて
//配列→リスト的なデータ。インデックスでアクセス
const alphabet = ["A", "B", "C"];
//オブジェクト(属性の集合、情報のまとまり。キーでアクセス)
const human = {
name: "Taro", age: 20,
name: "Jiro", age: 30
};
5. オブジェクト(クラス)
JavaScriptでは、オブジェクトはプロパティの集合(キー(プロパティ名)と値(プロパティ値)のペアからなるデータの集合体)であり、クラスはオブジェクトを作成するための設計図。
// オブジェクト
let person = {
name: "John",
age: 30,
greet: function() {
console.log(`こんにちは、私の名前は${this.name}です`);
}
};
person.greet(); // 出力: こんにちは、私の名前はJohnです
// クラス
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`こんにちは、私の名前は${this.name}です`);
}
}
const person1 = new Person("Jane", 25);
person1.greet(); // 出力: こんにちは、私の名前はJaneです
6. イベントハンドリング
クリックしたりスクロールしたりしたら、関数を起動。
ここは変わりないか、とおもったらアロー関数も使えてた。
アロー関数だと、this
の動作が外側のスコープにバインドされる。
// クリックイベントの処理
document.getElementById("myButton").addEventListener("click", function() {
alert("ボタンがクリックされました!");
});
//アロー関数なら
document.getElementById("myButton").addEventListener("click", () => {
console.log("ボタンがクリックされました!");
});
// スクロールイベントの処理(ページの中央に到達したら)
window.addEventListener("scroll", function() {
if (window.scrollY > document.body.scrollHeight / 2) {
console.log("ページの中央に到達しました");
}
});
//既存の関数をイベント時に呼び出す場合******************
// 既存の関数
function greet() {
console.log("ボタンがクリックされました!");
}
// イベントハンドラで関数を呼び出す
document.getElementById("myButton").addEventListener("click", greet);
// 既存の関数
function changeColor(color) {
document.body.style.backgroundColor = color;
}
// ボタンのクリックで色を変える
document.getElementById("colorButton").addEventListener("click", function() {
changeColor("lightblue"); // 関数を呼び出して背景色を変更
});
7.非同期処理 (Async/Await)
なんかPythonでもやったな。
さて同期と非同期の違いってなんでしょう。(前回の記事の復習はこちら)
https://qiita.com/Atsulabo/items/5c205a029bf91037c88a
// 非同期処理の例
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
}
fetchData(); // 非同期でデータを取得
8.DOM操作 (jQueryとの違い)
まあここはね。でも自然とJSに戻ってきている気がするな。書き方が。
なんとなくね、JSのほうが書きやすいんだよね。長いのにさ。
// 純粋なJavaScript
document.getElementById("myElement").style.color = "red";
// jQuery
$("#myElement").css("color", "red");
9.仮想環境の開発基礎
多分ここから新しい分野。(私にとっては)
Pythonのような仮想環境は一般的でないが、npm
やnode
を使ってパッケージやプロジェクトを管理することができる
# 新しいプロジェクトを作成し、パッケージをインストール
npm init -y # プロジェクトを初期化
npm install express # パッケージ(例:Express)をインストール
10.Node.js基礎
Node.jsは、サーバーサイドでJavaScriptを実行するための環境
// Node.jsでの簡単なHTTPサーバー
const http = require('http');
const server = http.createServer((req, res) => {
res.write('こんにちは、Node.js!');
res.end();
});
server.listen(3000, () => {
console.log('ポート3000でサーバーが動作しています');
});
11.モジュールハンドラ
Node.js
では、require()
を使って他のモジュールをインポート
ここらへんは微妙にPythonと似てるな
// myModule.js
module.exports.greet = function() {
console.log("モジュールからこんにちは!");
};
// main.js
const myModule = require('./myModule');
myModule.greet(); // 出力: モジュールからこんにちは!
12. テスト技法の基礎
ちょっとややこしいので再復習がひつようかn
Jestを使った例
npm install --save-dev jest
npm test
// Jestを使った例(npmでインストールが必要)
const sum = (a, b) => a + b;
test('1 + 2は3になる', () => {
expect(sum(1, 2)).toBe(3);
});
事前に書いたファイルのテストもできるが下準備が必要
1)まず functions.jsファイルを作る
// functions.js
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
module.exports = { add, multiply };
2)Jestによるテスト
// functions.test.js
const { add, multiply } = require('./functions'); // 関数をインポート
describe('Test functions', () => {
test('add function adds two numbers correctly', () => {
expect(add(1, 2)).toBe(3); // add関数が正しいかテスト
});
test('multiply function multiplies two numbers correctly', () => {
expect(multiply(2, 3)).toBe(6); // multiply関数が正しいかテスト
});
});
3)テストの実行
いつものようにインストール
npm install --save-dev jest
その後、package.json
のscripts
セクションに以下を追加
"scripts": {
"test": "jest"
}
そして上で実施したのと同じようにテスト
npm test
テスト結果
PASS ./functions.test.js
Test functions
√ add function adds two numbers correctly (5 ms)
√ multiply function multiplies two numbers correctly (1 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
余談: 標準入力の書き方
paizaで使える。これをやる前にメモっておいたのがあったので
まとめておく。
// 標準入力されたデータを全部変数inputにいれる
// 標準入力されたデータは全部文字列になることに注意
const input = require('fs').readFileSync('/dev/stdin', 'utf8');
// データを改行コードで分割して配列にいれる
const lines = input.trim().split('\n');
// 文字列を数値にするにはこうする Intにparseすると覚えればOK
const N = parseInt(lines[0]);
//出力(例
console.log(N);
ちなみに3行目・5行目はPHPでもあったメソッドチェーン的な書き方。
3行目はJSやってて初めてみた。下記のような意味。
fs
ファイルを操作するためのモジュール(※)
require('fs')
fsモジュールを読み込む
readFileSync
ファイルを同期的に読む関数(※)
/dev/stdin
標準入力(キーボード入力)のパス。ちなみに前行の「ファイル」というのはこれのこと。たまたま標準入力になっているが、他のファイルパスでもよい
※モジュールは他のJSファイルから関数や変数を持ってきたり、逆に提供したりする仕組みで、fsはNode.jsの組み込みモジュール(ファイルシステム)。昔のJS(CommonJS)からあるのでrequireでもってくる。他にはpath
(ファイル操作),http
,os
,crypto
(暗号用)などがある。モジュールについては別項
※「同期的に読み込む」とは、プログラムがその処理の完了を待ってから次へ進むこと。
この処理の場合はファイルが全部読み込まれてから次の行に進むことを意味する。
逆に非同期だと処理の完了を待たず先に進むことになる。並列処理に使える。この場合はCallback
やPromise
で受け取る。
pythonやPHPでもあったが、同期・非同期の違いが自分でも曖昧だったので改めて。