AngularJSで関数を動かして分かったこと

AngularJSを使っていて気になったことメモ

関数の書き方はいくつかある。

```javascript:methodTest.js
let app = angular.module('methodTest', []);

app.controller('meController', function($scope) {

  // その1 普通に定義
  let callA = function() {
    console.log('a');
  }

  // その2 依存サービス(?)に定義
  $scope.callB = function() {
    console.log('b');
  }
  
  // その3 Controllerに定義？  
  this.callC = function() {
    console.log('c');
  }
})
```

書き方によって呼び出せたり呼び出せなかったりするので色々確認。

## 関数を画面から呼ぶ

```html:methodTest.html
<!doctype html>
<html ng-app="methodTest">
<head>
<title>Angularテスト</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="./methodTest.js"></script>
</head>
<body>
<div ng-controller="meController as meCtrl">
	<!-- ボタン押下でそれぞれのメソッド呼出 -->
	<button ng-click="callA()">callA</button>
	<button ng-click="callB()">callB</button>
	<button ng-click="callC()">callC</button>
</div>
</body>
</html>

```
![buttons.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575553/4296e2a2-a07c-e049-3aad-2bd5f32d976a.png)


A、B、Cを順に押した出力結果

```
b
```
callA、callCが呼び出せない。(Console上でエラーは出力されない)

Controllerを指定してみる。

```html:methodTest.html

<div ng-controller="meController as meCtrl">
	<!-- meCtrl.をつける -->
	<button ng-click="meCtrl.callA()">callA</button>
	<button ng-click="meCtrl.callB()">callB</button>
	<button ng-click="meCtrl.callC()">callC</button>
</div>

```

A、B、Cを順に押した出力結果

```
c
```
callCが呼べるように。
callA、callBは呼び出せない。(Console上でエラーは出力されない)

callA式もHTMLから呼び出せないか模索
onClickにしてみる。確認用にcallDボタンも増やす。

```html:methodTest.html

<div ng-controller="meController as meCtrl">
	<!-- onClickにしてみる -->
	<button onClick="callA()">callA</button>
	<button ng-click="callB()">callB</button>
	<button ng-click="meCtrl.callC()">callC</button>
	<button onClick="callD()">callD</button>
</div>

```
```javascript:methodTest.js
app.controller('meController', function($scope) {
  // その1 普通に定義
  let callA = function() {
    console.log('a');
  }

  // その2 依存サービス(?)に定義
  $scope.callB = function() {
    console.log('b');
  }
  
  // その3 Controllerに定義？  
  this.callC = function() {
    console.log('c');
  }
})

// その4 Controllerの外に出す(もはやAngularJSではない)
let callD = function() {
	console.log('d');
}
```

![buttons2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575553/73dd2415-25c6-5ec4-12ff-23de50d67de3.png)

A、B、C、Dを順に押した出力結果

```
Uncaught ReferenceError: callA is not defined
    at HTMLButtonElement.onclick (methodTest.html:10)
b
c
d
```
callAは参照できない。無理そう。


### まとめ
```javascript:methodTest.js
app.controller('meController', function($scope) {
  // 画面からは呼べない
  let callA = function() {
    console.log('a');
  }

  // callB()で画面から呼べる
  $scope.callB = function() {
    console.log('b');
  }
  
  // [コントローラー].callC()で画面から呼べる
  this.callC = function() {
    console.log('c');
  }
})

// 画面から呼べる
let callD = function() {
	console.log('d');
}
```

## 関数を関数の中から呼ぶ
コードを少し修正。callAは$scope.callAViaを経由して呼ぶ。


```html:methodTest.html
<div ng-controller="meController as meCtrl">
	<button ng-click="callAVia()">callA</button>
	<button ng-click="callB()">callB</button>
	<button ng-click="meCtrl.callC()">callC</button>
</div>

```
```javascript:methodTest.js
app.controller('meController', function($scope) {
  // その1 普通に定義
  let callA = function() {
    console.log('a');
  }
  
  // その1を呼び出す用
  $scope.callAVia = function() {
    callA();
  }

  // その2 依存サービス(?)に定義
  $scope.callB = function() {
    console.log('b');
  }
  
  // その3 Controllerに定義？  
  this.callC = function() {
    console.log('c');
  }
})
```

![buttons.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575553/bb8cea11-c5f0-d011-e817-8e6ebfeb4636.png)

A、B、Cを順に押した出力結果

```
a
b
c
```


### letで定義した関数から呼ぶ

```
  let callA = function() {
    console.log('a');
    $scope.callB();
    this.callC();
  }

```
callA関数の中から$scope.callBとthis.callCを呼び出す。

callAボタンを押した出力結果

```
a
b
TypeError: this.callC is not a function
```

callCは呼び出せない。
`this.callC is not a function`で関数じゃないと言われているので`this.callC;`としたところエラー無しで何も出力されなくなる。
試しに以下の書き方でもエラーとなる。

```
$scope.callC();
callC();
```

(2020/6/17追記)
callAをアロー関数にすると呼び出しに成功

```
  let callA = () => {
    console.log('a');
    $scope.callB();
    this.callC();
  }
```
出力結果

```
a
b
c
```

### 依存サービス($scope)に定義した関数から呼ぶ
```javascript:methodTest.js
  let callA = function() {
    console.log('a');
  }

  $scope.callB = function() {
    console.log('b');
    callA();
    this.callC();
  }
```

callBボタンを押した出力結果

```
a
b
TypeError: this.callC is not a function
```

以下の書き方でもエラーとなる。

```
$scope.callC();
callC();
```

(2020/6/17追記)
callBをアロー関数にすると呼び出しに成功


```
  $scope.callB = () => {
    console.log('b');
    callA();
    this.callC();
  }
```

出力結果

```
b
a
c
```


### Controllerに定義？した関数から呼ぶ


```javascript:methodTest.js
  let callA = function() {
    console.log('a');
  }
  
  $scope.callB = function() {
    console.log('b');
  }
  
  this.callC = function() {
    console.log('c');
    callA();
    $scope.callB();
  }
```

callCボタンを押した出力結果

```
c
a
b
```

全て呼び出せる。

### まとめ

```
app.controller('meController', function($scope) {
  // 「$scope.」からも「this.」からも呼び出せる
  let callA = function() {
    console.log('a');
  }
  
  // 「let」からも「this.」からも呼び出せる
  $scope.callB = function() {
    console.log('b');
  }
  
  // 「let」からも「$scope.」からも呼び出せない
  // 「let」、「$scope.」をアロー関数にすると呼び出せる
  this.callC = function() {
    console.log('c');
  }
})

```

## 総まとめ

→から↓を呼び出す表でまとめ。

|  | html | let | $scope | this | let(アロー関数) | $scope(アロー関数) |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| let  |  × | 〇 | 〇 | 〇 |-|-|
|  $scope | 〇 | 〇 |〇 | 〇 |-|-|
|  this | 〇 | × | × | 〇 |〇|〇|

let同士、$scope同士、this同士の呼び出しも確認したところ問題なく呼べる。
思ったより挙動の違いがあって驚いた。何故。
~~AngularJSマスターにとっては当たり前体操なのかもしれない...自分はよく分かっていなかったので整理~~
コメントから、AngularJSの仕様とかではないらしい。普通にJavaScriptの勉強になりました。
なるほどなぁ

アロー関数と同様にthisを一度変数に入れてもcallCを呼び出せました。

## 参考
https://html5experts.jp/canidoweb/16732/


## 追記、修正
2020/6/17
Angular、Angular.js → AngularJSに修正
アロー関数について追記