ここが違くてここは同じだよPythonとJavaScript

# この記事は何の記事？
Python と JavaScript で動きが違う点・同じ点をまとめた記事です

違う点・同じ点なんていくらでもあると思いますが，
個人的に痛い目を見た事例について取り上げていきます

他にこんなのもあるよなどあれば是非教えていただきたいです

では本編スタートです

## 変数のスコープ・宣言・代入
Python の場合，宣言だけするということはできなく，
代入したときに変数が作られます
[www.w3schools.com](https://www.w3schools.com/python/python_variables.asp)
```Python
hensu = "あたい" # これだけ
```

JavaScript の場合，宣言と代入はそれぞれ分けられます

```javascript
// 宣言と代入一緒に
let hensu = "あたい" 

// 宣言と代入をわけて
let sengen
sengen = "せんげん"
```

ということで例を見ていきます
以下の流れを確認します

1. 変数 `hensu` を出力する（1 回目）
1. 変数 `hensu` に値を代入する関数 `kansu` を呼び出す
1. 変数 `hensu` を出力する（2 回目）

まず Python の例です
1 回目, 2 回目共に `xx` が出力されます
関数の外にある変数 `hensu` と，
関数 `kansu` 内の変数 `hensu` は，スコープが異なるので名前が同じな別の子
よって関数の外にある変数 `hensu` には `"ww"` は代入されていません
```Python
# Python の挙動
hensu = "xx" # 関数の外にある hensu
def kansu():
  hensu = "ww" # 関数 kansu 内の hensu
print(hensu) # xx
kansu()
print(hensu) # xx
```

ではでは JavaScript ではどうかというと
先ほどの Python の例とは異なり，
関数 `kansu` の `hensu` は，
関数の外にある `hensu` と同じ子です
よって，関数 `kansu` の処理で関数の外にある `hensu` に `"ww"` が代入され，
1 回目は `"xx"` が出力され，
2 回目は `"ww"` が出力されます
```javascript
// JavaScript の挙動
let hensu = "xx" // 関数の外にある hensu
function kansu() {
    hensu = "ww" // 関数の外にある hensu と同じ子
}
console.log(hensu) // xx
kansu()
console.log(hensu) // ww
```
因みに上記の JavaScript の挙動は，
Python でいうところの，`global` を使った時と同じ挙動になります

```Python
# Python の挙動
hensu = "xx"
def kansu():
  global hensu # グローバル変数の hensu であることを明示する
  hensu = "ww"
print(hensu) # xx
kansu()
print(hensu) # ww
```

## 関数の定義にいない引数を関数呼び出しで使う
まず以下の関数を定義します

- arg_nothing()
- arg_something(arg1, arg2, arg3)

この関数たちを以下のように呼び出します

- arg_nothing(123) # 定義にいない引数を使う
- arg_something(1) # 定義より引数の数が少ない
- arg_something(1, 2, 3, 4) # 定義より引数の数が多い

結論から言うと，
**Python** は **エラー** がでるが，**JavaScript** は **エラーにならない**
ということです

ではまずは Python から

```Python
# Python の挙動
# 定義にいない引数を使う
def arg_nothing():
  print("arg_nothing が呼び出されました")

arg_nothing(123)
# TypeError: arg_nothing() takes 0 positional arguments but 1 was given
```
引数 0 個のはずなのに 1 個引数が与えられたよっていうエラーがでます

```Python
# Python の挙動
# 定義より引数の数が少ない
def arg_something(arg1, arg2, arg3):
  print("arg_something が呼び出されました")
  print(arg1, arg2, arg3)

arg_something(1)
# TypeError: arg_something() missing 2 required positional arguments: 'arg2' and 'arg3'
```
おいおい，arg2 と arg3 はどうしたよっていうエラーがでます

```Python
# Python の挙動
# 定義より引数の数が多い
def arg_something(arg1, arg2, arg3):
  print("arg_something が呼び出されました")
  print(arg1, arg2, arg3)

arg_something(1, 2, 3, 4)
# TypeError: arg_something() takes 3 positional arguments but 4 were given
```
引数 3 つのはずなのに 4 つ与えられたよっていうエラーがでます

続いて JavaScript

```javascript
// JavaScript の挙動
function arg_nothing() {
    console.log("arg_nothing が呼ばれました")
}

arg_nothing(123) // 定義にいない引数を使う

function arg_something(arg1, arg2, arg3) {
    console.log("arg_something が呼ばれました")
    console.log(arg1, arg2, arg3)
}

arg_something(1, 2, 3) // 定義より引数の数が少ない
arg_something(1, 2, 3, 4) // 定義より引数の数が多い

// 以下実行結果です

// arg_nothing が呼ばれました

// arg_something が呼ばれました
// 1 undefined undefined

// arg_something が呼ばれました
// 1 2 3
```

JavaScript の場合
定義にいない引数を渡した場合 `undefined` として扱われ，
エラーが起きません

## 可変長位置引数, 残余引数とアンパック
まず可変長位置引数と残余引数が何かについてざっくりと説明です
関数の定義の時に何個渡されるかわからないけど，
まとめて扱いたい時に使う，可変長の引数のことです
Python では可変長位置引数といい，JavaScript では残余引数といいます

次にアンパックですが，
配列など複数の値がまとまっているものをバラで扱うときに使うやつです

以下まとめです

- Python
    - 可変長引数の名前： 可変長位置引数
    - 可変長引数の記号：`*` 例：）`def f(*args):`
    - 可変長引数の型：list
    - アンパックの記号：`*` 例：）`*args`
    - アンパックの型：tuple
- JavaScript
    - 可変長引数の名前：残余引数
    - 可変長引数の記号：`...` 例：）`function f(...args)`
    - 可変長引数のインスタンス：Array
    - アンパックの記号：`...` 例：）`...args`
    - アンパックのインスタンス：Array

以下コードの具体例です
```Python
# Python の例
ar1 = [1, 2, 3]
ar2 = [4, 5, 6]
print([*ar1, *ar2]) # [1, 2, 3, 4, 5, 6]
print(type([*ar1, *ar2])) # <class 'list'>

def ar(*ars):
  print(ars) # ([1, 2, 3], [4, 5, 6])
  print(type(args)) # <class 'tuple'>
  for a in ars:
    print(a)
    # [1, 2, 3]
    # [4, 5, 6]

ar(ar1, ar2)
```

```javascript
// JavaScript の例
ar1 = [1, 2, 3]
ar2 = [4, 5, 6]
console.log([...ar1, ...ar2]) // [1, 2, 3, 4, 5, 6]
console.log([...ar1, ...ar2] instanceof Array) // true

function ar(...ar) {
    console.log(ar) // [Array(2)]
    console.log(ar instanceof Array) // true
    for (a of ar) {
        console.log(a)
        // (2) [Array(3), Array(3)]
    }
}

ar([ar1, ar2])
```

## self と this
Python には `self` ,
JavaScript には `this` と似たようなキーワードがあります

どちらも何かオブジェクト自身のことを指す雰囲気があります
ですが色々と違うので見ていきます

まずは単独で確認してみます

```Python
# Python で確認
print(self)
# NameError: name 'self' is not defined
```
Python の場合，`self` ？知らない子ですねと言われます

```javascript
// JavaScript で確認
console.log(this)
// Window {window: Window, self: Window, document: document, name: '', location: Location, …}
```
JavaScript の場合，`Window` オブジェクトが表示されます

とここまでは良いのですが，
大きな違いとして，JavaScript には関数を作る方法が大きく分けて，
関数宣言と関数式があり，更に関数式には普通の関数式とアロー関数があります
これの何が問題かというと，メソッド呼び出しと関数呼び出しの時，
`this` の値が普通の関数式かアロー関数かで異なるという点です
詳しくはこちらの記事が参考になります
https://jsprimer.net/basic/function-this/


## 参考
- [JavaScript の引数の挙動についての参考](https://job-support.ne.jp/blog/javascript/basic-argument#5f7427bdb8726c166a44000a-f8d573a42f37f126c4e8b65c)
- [JavaScript の let の巻き上げについて](https://qiita.com/jonakp/items/c943c8d457871fa6ceb6#let%E3%81%AB%E3%82%88%E3%82%8B%E5%A4%89%E6%95%B0%E3%81%AE%E5%B7%BB%E3%81%8D%E4%B8%8A%E3%81%92)
- [thisの挙動について](https://jsprimer.net/basic/function-this/)
- [thisの挙動についてはこちらも参考になります](https://zenn.dev/geen1/articles/186631c713e6d8)