44
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptの関数について

Last updated at Posted at 2017-09-27

基本編

関数とは

  • ロジックの定義のこと
  • 関数として定義しておくことで同じロジックを何度も書かなくてよくなる
  • 関数を呼ぶだけでいつでも同じ処理を実行できちゃう

関数の宣言と実行

宣言

  • JavaScriptでは関数の定義にfunctionを使う
  • 引数を受け取るための()をつける
  • {}の中にロジックを書く
// 名前がない関数は()で囲わないとエラーになる
(
  function() {
    console.log('hello');
  }
)

実行

  • 関数の定義に()をつけることで実行される
// 名前がない関数は()で囲わないとエラーになる
(
  function() {
    console.log('hello');
  }()
  // hello
)
  • ※このように定義に直接()をつけて実行する関数のことを即時関数と呼ぶ
    • 定義して即時に実行されているので

関数に名前をつける

  • 上記の例では定義を直接実行しているので、「関数を呼ぶだけでいつでも同じ処理を実行できちゃう」とはならない
  • なので関数の定義に名前をつける
function sayHello() {
  console.log('hello');
}
  • 関数名に()をつけると実行できる
  • これで一度定義すれば呼び出すだけで何度でも実行できる
sayHello(); // hello
sayHello(); // hello
sayHello(); // hello

関数式

  • JavaScriptでは関数を変数に代入することができる
  • 変数に入れる時は関数に名前をつけなくても平気
  • 実行は変数名に()をつける
var sayHello = function() {
  console.log('hello!');
}
sayHello(); // hello!
  • sayHelloという変数に関数の定義が入っているので、「関数の定義に()をつけることで実行される」の形になっている
sayHello();
// ↑は↓が実行されているということ
function() {
  console.log('hello!');
}()

アロー関数

  • ES2015から使えるようになった関数の宣言方法
  • function()() =>に置き換わるイメージ
  • アロー関数には名前をつけられないので変数に代入して実行する
const sayHello = () => {
  console.log('hello!!');
}
sayHello(); // hello!!
  • 処理が一行だけの時は{}を省略して書くことができる
const sayHello = () => console.log('hello!!');
  • これまでのルールと同様で関数の定義に直接()をつけて実行することもできる
(() => console.log('hello!!'))();
// hello!!

まとめ

  • 関数は定義に()をつけると実行できる
  • 関数の定義に名前をつけることができる
  • 関数の定義を変数に代入できる
  • アロー関数を使うと省略して書ける

応用編

関数を受け渡す

  • 関数は定義に()をつけることで実行できる
  • なので定義を変数に入れてたらい回しにして実行したい時に()をつける、なんていう使い方ができる

サンプル

var sayHello = function() {
  console.log('hello!!!');
}

var greet = function(someMethod) {
  console.log('greet!');
  someMethod();
}

// 関数の定義を引数で渡す
greet(sayHello);
// greet
// hello!!!
  • sayHelloとgreetの2つの関数がある

    • sayHelloはコンソールにhello!!!と出すだけ
    • greetはコンソールにgreetと出した後、引数で受け取った関数を実行している
  • greetの実行

    • 引数にsayHello(=関数の定義)を渡している
      • ここでは定義を渡しているだけ()がついていないのでsayHelloは実行されない
  • greet実行時の動き

    • まずコンソールにgreetが表示される
    • 次に引数で受け取った関数を実行し、コンソールにhello!!!と表示される
    • someMethodの中身は実行時に渡されたsayHelloで、sayHelloの中身は関数の定義
    someMethod()
    // ↑は↓が実行されているということ
    function() {
      console.log('hello!!!');
    }()
    

classを使うケース

  • classはES2015から使える書き方(今回は必要なところしかふれない)

クラスメソッドの作り方

  • classの中にメソッド名()と書くことでメソッドを作ることができる
  • 実行する時はnewしたインスタンスに対してメソッドを呼ぶ
class Sample1 {
  sayHello() {
    console.log('hello');
  }
}
var sample1 = new Sample1();
sample1.sayHello(); // hello

thisの変化

thisが変わってエラーになるパターン

  • メソッドの中のthisはメソッドを呼び出した時の.の前の値
    • sample.greet()と呼んだ場合はthisはsampleになる
  • メソッドの中でfunctionが出てくるとthisが変わってしまう
class Sample2 {
  constructor() {
    this.members = ['Taro', 'Ichiro', 'Jiro'];
  }

  sayHello(name) {
    console.log(`hello ${name}`);
  }

  greet() {
    // sample2.greet()と呼んだのでthisはsample2(Sampleクラスのインスタンス)
    this.members.forEach(
      // functionの中に入るとthisが変わってしまう
      function(member) {
        // ここのthisはsample2(Sampleクラスのインスタンス)ではないのでsayHelloメソッドが見つからずエラーになる
        this.sayHello(member);
      }
    );
  }
}
var sample2 = new Sample2();
sample2.greet();

bindを使ってthisをコントロールする

  • thisが変わってエラーが出るのを防ぐためにbindを使う
  • 関数の定義に対して.bind(xxx)をつけるとxxxの値がthisとして扱われる
class Sample3 {
  constructor() {
    this.members = ['Taro', 'Ichiro', 'Jiro'];
  }

  sayHello(name) {
    console.log(`hello ${name}`);
  }

  greet() {
    // sample3.greet()と呼んだのでthisはsample3(Sampleクラスのインスタンス)
    this.members.forEach(
      // functionにbind(this)をつけている
      function(member) {
        // thisの値はsample3(Sampleクラスのインスタンス)なので問題なく動く
        this.sayHello(member);
      }.bind(this)
    );
  }
}
var sample3 = new Sample3();
sample3.greet();
// hello Taro
// hello Ichiro
// hello Jiro

アロー関数でのthis

  • アロー関数を使うとデフォルトで.bind(this)したのと同じ動きをする
    • より正確には、アロー関数はthisをもたないので1つ上のスコープのthisが使われるという動きをしている
class Sample4 {
  constructor() {
    this.members = ['Taro', 'Ichiro', 'Jiro'];
  }

  sayHello(name) {
    console.log(`hello ${name}`);
  }

  greet() {
    this.members.forEach(
      (member) => {
        // thisの値はsample4(Sampleクラスのインスタンス)なので問題なく動く
        this.sayHello(member);
      }
    );
  }
}
var sample4 = new Sample4();
sample4.greet();
// hello Taro
// hello Ichiro
// hello Jiro

まとめ

  • 関数は定義に()をつけることで実行できるので、定義をたらい回しにして使いたい時に実行できる
  • 関数/メソッドのなかに関数がある場合はthisの変化に注意
  • bindを使うとthisの制御ができる
  • アロー関数を使うとthisの制御を勝手にやってくれる
44
50
1

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
44
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?