最前提として、私は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
};
余談: 標準入力の書き方
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でもあったが、同期・非同期の違いが自分でも曖昧だったので改めて。