関数とは
ある処理に名前を付けて、その名前で処理を呼び出せるようにすること
戻り値などの概念はよくあるので割愛。
Tips:式を計算することを「評価する」と呼ぶ
引数
関数に渡す値を実引数。
本物の名前・実際の名前で渡してるから実引数。
関数が受け取る値を仮引数。
本物の名前じゃなくて、関数の中で仮につけてる引数の名前だから仮引数
let hunter: string = '狩人';
function growOld(a):string { //$aという変数名はここでしか使っていないので仮引数
return '古' + $a
}
growOld(hunter); //これは本来の変数名を引数として渡しているから実引数
仮引数は実引数を別の変数に入れて処理をしているので、
実引数となっている変数そのものに変化があるわけではない。
値のコピーを渡しているだけなので、本体には影響がない。
この引数に渡す変数がオブジェクトの場合は注意。
オブジェクトを引数に指定すると参照渡しになる。
仮引数の中身はオブジェクトの参照になってしまい、
関数の中でその仮引数に対して何かを行うとオブジェクトにも変化が起きてしまう
残余引数
本来、仮引数は引数としたい変数の数だけ指定するもの
function test (a, b, c) { //引数としたい数だけ指定
//処理
}
ただ、こんなことができるらしい
function test (a, ...x){ //一つ目だけ指定して、あとの引数は全部$xの中に詰め込む
//処理
}
実例
let soldiers:string[] = [
'ビッグボス',
'オセロット',
'クワイエット',
'ヴェノム・スネーク',
'和平',
];
let spies:string[] = [
'チコ',
'パス',
];
let scientists:string[] = [
'ヒューイ',
'ストレンジ',
];
function test(a, ...x) {
console.log(a)
console.log(x)
}
やはり、xという変数にふたつの配列がまとまっている。
ということはこうすれば仮引数にまとめてしまった値の一つずつを取得できるはずだ。
function test(a, ...x) {
console.log(a)
console.log(x[0])
console.log(x[1])
}
関数の型注釈
関数にも型注釈がある。
型注釈とは、変数・定数に入れることの出来る値を決めておくこと。
何に対しての型注釈なのか?
・戻り値
・引数
に対しての型注釈だ。
function test(a: number):string { // aの後にやっているのが引数の型注釈、:stringの部分が戻り値の型注釈
if (a > 10){
return 'aは11以上' //当然戻りはstring
} else {
return 'aは10以下'
}
}
関数の中で処理を終えて、戻り値がないこともある。
そんな時は戻り値の型注釈に
:void
を使う
any型
今迄TypeScriptを見るたびに「なんだこれ?」となっていたところ。
要は なんでもあり という事らしい
TypeScriptでは型を決めておくことで、エラーを少なくしたいという意図がある。
従来のJavaScriptでは型が勝手に変換されてしまうため、エラーが起きてしまうことがあった。
それを防ぐための型注釈なのに、
なんでもありにしてしまっては、TypeScriptの意義が失われてしまう。
なので、基本的には使わないほうがいいだろう。
基本使ったらダメなものとして覚えておくのがよさそう。
レビューでも使ったら指摘を受けそうなポイント
引数のデフォルト値
引数を設定しなかった場合に、勝手にその値を設定してくれる。
function test(a:string = 'ジョニー'): void {
console.log(a)
}
test(); //ここで引数をしていしなくていい
ただし、プログラム側で引数を省略してるのかどうかが判断できない場合は使えない
function test(b='ジョニー' ,a) {
//
}
test('メリル') //この場合、test関数的にはbを省略してるのか、aを省略してるのかが分からない
なので、複数の引数があり、そのうちのいくつかを省略可能な場合は、
必須の引数をまず書き、その後ろに省略可能なものを設定することになる。
もしくは引数が一つしかなければ、省略可能としてデフォルトを設定できる。
複数の仮引数があり、どうしても最初の一つ目をデフォルト引数にして、そのデフォルト値を使いたい場合、
test(undifined, '二つ目の仮引数')
みたいにすることもできる
undifinedは何も渡していないと同じになり、デフォルト引数を未定義にするわけではない
引数の分割代入
関数の仮引数に分割代入することができる
分割代入は複数のデータを持つもののうちの、一部だけを代入する。
いちいち配列の中身を取り出す処理をしなくてよく、たいへん便利
let soldiers:string[] = [
'ビッグボス',
'オセロット',
'クワイエット',
'ヴェノム・スネーク',
'和平',
];
function test([a,b,...x],:string[]) :string {
console.
}
間の要素を飛ばす
let soldiers:string[] = [
'ビッグボス',
'オセロット',
'クワイエット',
'ヴェノム・スネーク',
'和平',
];
function test([a,,c]:string[]) :void {
console.log(a) // ビッグボス
console.log(c) // クワイエット
}
NaN
Not a Number
数値型じゃないことを指す。
デフォルト引数
分割代入でもデフォルト引数を設定できる
const spies:string[] = [
'チコ',
'パス',
]
function test(a=0, b=0) :void{
console.log(a)
console.log(b)3
}
配列全体にデフォルトの引数を設定することもできる
const spies:string[] = [
'チコ',
'パス',
]
function test(list :string[]=['スカルフェイス'] ):void {
console.log(list)
}
test(); //引数を設定しない
// ['スカルフェイス']が出力
関数式
変数の中に関数を入れるみたいな形式で書く式。
普通なら、以下のように書く。
function 関数名() {
//
}
別の書き方として、以下の書き方がある。
これを関数式と呼ぶ。
const test = function() { //変数・定数名が関数の名前になる
//
}
test(); //呼び出し方は一緒
アロー関数
初心者の壁。
今迄なんとなく避けてきた書き方。
なんのためにあるのか、を知ればむしろ便利だなと思うようになった。
メリットは
・短く書ける
こと。
やれることは
・functionの省略
・()の省略
・returnの省略
書き方としては関数式に近い。
const test = 仮引数 => returnする値(式)、または実行する処理
// 複数引数がある時は()は省略不可
// 矢印の後の処理が一行で済まないときは{}は省略不可
const test = (a:string,b:string) : string => {
console.log(a);
return b;
}
・{}を書いてしまうことで、returnが省略できなくなる
・仮引数の()を省略すると、型注釈が使えなくなる
型ガード
ユニオン型のような、どの型が使われるか判別がつかないものは、その先の処理でどう扱うかを考えないといけない。
string | number
の型注釈があったとして、
stringの前提でコードを書いてしまうと、numberだったときにエラーになる恐れがある。
そんなことを防ぐのが型ガード。
//この処理はstringの時しかさせたくない
if (typeof x === "string") {
//
}
要は、typeOfメソッドを使って型を判別して、ある型の場合のみこの処理を行わせよう、という技法のことを型ガードとかっこつけて名付けている。
これをやっていると、毎回typeofの判定いれるのめんどくさいなってなってくる。
そしてこんな関数にまとめる
function isString(x:string | number):boolean { //この関数はstringかnumberを受け取れる
return typeof x === 'string' //xがstringならtrueを返す
}
if (isString(x)){ //コンパイラがここでエラーを出す。xが文字列かどうかわかんねえよ!と怒られる
//xの型がstringのときにしかできない処理(Stringオブジェクトのメソッド使用など)
}
エラーになってしまうのを避けるにはx is stringを戻り値の型注釈につける
function isString(x:string | number):x is string { //この関数で返す値の型は絶対stringだよ!とコンパイラに教えてあげる
return typeof x === 'string'
}