導入
どうも、大辞林ティーです。
今緊急で記事書いてるんですけど(緊急性はない)、「JavaScriptの関数ってわかりずらくね?」ということでそなへんをまとめます。
説明は荒いけど、情報の足がりになれば幸いです
言葉遣いが間違っていたりするけど大目に見てね!
JSの値
まずJavaScriptの基本の型をまとめましょう
| 型名(tsなど) | 説明 | 例 |
|---|---|---|
undefined |
未定義 | ({a:1}).b |
object |
配列や辞書など |
[], {a:1}, null
|
boolean |
真偽値 |
true, false
|
number |
数字 | 1 |
string |
文字列 | "hello world!" |
function |
関数 |
()=>{}, function (){}
|
特徴としては、数値が一つの型としていることや、 関数が値として扱えることでしょうか。
関数の定義
function 関数名(引数) {
// 処理
}
これは基本の書き方ですね。
関数に名前を持たせて定義しています。
この時点では関数は実行されず、
関数名(引数);
などとすると実行ができます。
無名関数
代入
さて、ここが少し難しい
関数って名前がなくても定義できるんです。
ただ、定義しただけだと呼び出せなくて意味がありません。
なので、例えばtest, test2という定数に代入してみましょう。
const test = function (引数) {
//処理
}
const test2 = (引数)=>{
//処理
}
無名関数には書き方が2つあります。
細かい違いはあるそうですが、今は気にしなくていいでしょう。
今回やったのは、
- 関数の定義
-
test,test2に関数を値としてを代入
です。なので、まだ関数は実行されていません。
これを実行するには、
test(引数);
test2(引数);
などとすればいいわけです。
関数自体が値であり、それを定数に保存したものを呼び出す、という感じでしょうか
辞書、配列の値として使用
関数は値ですので、辞書型にも使えます。
// 辞書型を宣言
const testDict = {
testWord: "this is string",
testFunc: ()=>{
console.log("hello!");
}
}
// 関数を実行
testDict.testFunc();
// ログ: "hello!"
あまり見ませんが配列にも使えます
// 宣言
const testList = [1,2,3,(a)=>{
console.log(`hello ${a}!`);
}];
// 呼び出し
testList[3]('daijirin-tea');
// ログ: "hello daijirin-tea!"
即実行
関数();とすることで関数を呼べましたが、無名関数でも同じように呼べます。
((str)=>{
console.log(`nice to meet you, ${str}.`);
})("hogehoge");
// ログ: "nice to meet you, hogehoge."
(function(str){
console.log(`nice to meet you, ${str}.`);
})("hogehoge");
// ログ: "nice to meet you, hogehoge."
コールバック
さて、ここが問題です。
関数は値なので、関数の引数にも使える…というややこしいやつです
// 定義
function callbackTest(a,b,callback) {
const result = a + b;
callback(result);
}
// 呼び出し1
function exampleCallbackFunc(receivedStr) {
console.log(`a. ${receivedStr}!`);
}
callbackTest(1,3,exampleCallback);
// ログ: "a. 4!"
// 呼び出し2
callbackTest(1,3,(receivedStr)=>{
console.log(`b. ${receivedStr}!`);
});
// ログ: "b. 4!"
まず定義の部分です。
これはa, b, callbackという引数を取ります
callbackが関数だと仮定すると、callback(result);でその関数を呼びます
そして、呼び出し1。
exampleCallbackFuncという名前の関数を渡していますね。
引数はそれぞれ、(1,3,exampleCallback)→(a,b,callback)という名前となり、callbackTest内でのcallback(result);はexampleCallback(result);と同じことだとわかります。
そして、呼び出し2。
これは無名関数をそのまま渡しただけとなります。
(1,3,(receivedStr)=>{console.log(`b. ${receivedStr}!`);})→(a,b,callback)となります。
よって、callbackTest内では前者の無名関数()=>{...}がcallbackという名前で使用可能になりました。
コールバックって何がいいの?
通常のfuncitonだと、時間のかかる処理の返り値をうまく返せません。(気になる方はPromise, asyncなどで検索)
「この処理がしたいから5秒間停止して!」みたいなことはしてくれないんですね。
例えば5秒後に処理をしたければ、
console.log('処理を開始します');
setTimeout(()=>{
console.log('5秒が経ちました!');
},5000);
console.log('他の処理は停止されません');
// ログ: "処理を開始します"
// "他の処理は停止されません"
// そして5秒立つと…
// ログ: "5秒が経ちました!"
のようになります。
setTimeoutは第一引数の関数を第二引数(ms)の時間後に実行してくれる関数であり、第一引数はコールバック関数に当たります
ほかにも
これはコールバックとは呼ばなそうですが、関数を引数にとるものは他にもいます。
例えば、配列の並べ替えにはsort()を使いますが、その引数には順番の入れ替え方を指示する関数が取れます。
[8,9,6,7,5,3,4,1,2].sort((a,b)=>{
return a - b;
});
// = [1,2,3,4,5,6,7,8,9]
この関数は、2つの要素(a,b)を比べた時に、
-
a→bの順であるべきなら、負の数 - そのままでいいなら、0
-
b→aの順であるべきなら、正の数
を返すようにします。
最後に
関数が値となるのって変だし書き方も多くなるけど便利にもなるんだぜ、というお話でした