LoginSignup
1
2

More than 3 years have passed since last update.

javascript 再入門 1:関数は値です

Last updated at Posted at 2019-11-21

初めに

この記事は、javascriptを始めようと思った人が躓きやすいポイントを整理してお話したいと思います。

関数

関数定義は基本的に下に出てくる例のとおりです。

javascriptでは、関数は値という扱いになっています。
なので、変数や定数への割り当てを行えます。

const cubic = function (a) {return a**3};

そして、関数を別の関数の引数に渡すことも出来ます。

const myFunc = function (f) {return f(5)};
myFunc(cubic);

さらには、関数の返り値に関数を返すようにも出来ます。

const answerFunc = function (a) {
  return function (f) {
    return f(a);
  }
}

今どきの関数の書き方

オブジェクトのメソッドとして実装する場合

オブジェクトのメソッドとして実装したい場合は、以下のようにfunctionキーワードを省いて書くことが出来ます。
ついでに「:」も省略可能です。

const myPrototype = {
  setFoo (foo) {
    this.foo = `Hello ${foo}`;
    return this;
  },
  //可変長引数を取ってみる
  pipe (...f) {
    f.reduce((p, c) => c(p), this.foo);
    return this;
  },
  //分割代入
  pair ({x, y}) {
    this.foo = [x, y];
  },
  //配列の分割代入
  sum ([x, y]) {
    this.foo = {x, y};
  }
}

const myObj = Object.create(myPrototype, {
  foo: {
    writable: true,
    value: void 0
  }
});

myObj.setFoo('dog');
console.log(myObj.foo);

アロー関数式を使う

注)あるオブジェクトのメソッド内でこの方法を使うと、そのメソッドを呼び出した元のオブジェクトをthisとして、その関数のthisが束縛されます。
なので、あるオブジェクトのメソッドに直接アロー関数を書かないでください。
その場合は上記の略記法を使ってください。

//引数が一つの場合は()を省略できる
const f = a => a ** 3;

//可変長引数と分割代入が使える
const g = (...v) => r => r(...v)

先程の、関数を返す関数も以下のように書き直すことが出来ます。

const aFunc = a => f => f(a);

分割代入などの略記

新しい書き方の一つですが、今までのコードを踏まえて、改めて説明します。
関数定義や関数実行の () の中の書き方に特徴があるだけです。


// 関数内で引数全てを配列にして扱う。 引数指定の部分に(...引数名)と書く。
const a = ( (...v) => v.map(w => w * 5) )(1, 2, 3, 4, 5);
// [5, 10, 15, 20, 25]

// 配列を引数へ展開して代入する。 関数実行時に(...配列名)と書く。
const b = ( (a, b, ...c) => ({a, b, c}))( ...a );
// {a: 5, b: 10, c:[15, 20, 25]}

// オブジェクトのキー名を引数名として使いたい場合は、
// 引数指定の部分に({キー1, キー2, ...残りを受け取る引数名})と書く。
const c = ( ({a, c, ...o}) => ({d: c.pop(), e: a + o.b, c, ...o}) )( b );
// {a: 5, b: 10, c: [15, 20], d: 25, e: 15}

// 配列の分割代入をする。
const d = ( ([a, b, ...c]) => ({a, b, c}) )( a );
// {a: 5, b: 10, c:[15, 20, 25]}

上ではアロー関数だけで書きましたが、オブジェクトのメソッド定義の場合も同じです。

遅延評価とコールバック

遅延評価

例えば、以下のような定義をします。

//遅延評価する
const lazying = (...v) => f => f(...v);

//遅延評価出来るので、引数が先に決まって大丈夫。
const runner = lazying('Hello', ' Lazying', ' World');

//なんの関数を入れても引数が先に決まっている!
runner((...v) => alert(v.join('')));

コールバック

ある関数は、関数を引数に取るように最初から設計されています。
javascriptでは、関数がその場で実行されない形式を取ることが出来ます。
つまりは、遅延評価出来るわけです。
普段は正格評価なのですけれども、例えばあるイベント(ボタンがクリックされたなど)では、そのタイミングで渡された関数を実行しようとします。

javascriptでは、そういった非同期な処理を行うことが多いので、関数は自分を実行するための条件(具体的には実行可能な数の引数を渡せる条件)が整った段階で実行されると覚えてみてください。

const server = require('http').createServer();
server.on(
  'get',
  (q, s) => s.writeHead(200).end("Hello javascript")
);
server.listen(3000);

node.jsでの例です。
上の例の場合は、サーバーがgetメソッドでリクエストを受け取った時に、後ろの関数が実行され、qには、request に関するオブジェクトが、sには、responseに関するオブジェクトが自動で代入されます。

今回はここまで!

次回は、コールバック関数に他のコールバックの条件が入ったら…
そして、そういった複数に跨る遅延処理の書き方を紹介します。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2