背景: 自分は初心者なんだと改めて・・・
-
2年もPythonとかSwiftとか使うエンジニアをやっていて、「参照型」や「値型」を理解していなかったことに反省
-
未来の自分が、こんなしょうもないことでショックを受けていたのかと見返すための記事
-
以下は、今回のバージョン情報
バージョン macOS 13.3.1 JavaScript Node.js18.12.1 Python 3.9.6 Swift 5.8
実験と結果: 言語ごとに違う配列定義の挙動
-
実験1:
- JavaScript・Python・Swiftで同じ要素を持つ配列を比較したらその結果は
true
か?
- JavaScript・Python・Swiftで同じ要素を持つ配列を比較したらその結果は
-
結果1:
- JavaScriptだけ
false
サンプルと結果# 同じ内容の配列を定義 変数A = 配列[1、2、3、4] 変数B = 配列[1、2、3、4] # この結果はture?? ログ出力(変数A == 変数B) ## -> 結果 ## JavaScript -> false ## Python -> True ## Swift -> true
- JavaScriptだけ
-
実験2:
- JavaScript・Python・Swiftで配列を定義した後、別の変数に渡して、それに要素を追加したら、最初に定義した方は元のまま?
-
結果2:
- Swiftだけ
[1, 2, 3]
のまま
サンプルと結果# 配列を変数Aに定義した後、別の変数Bに渡す 変数A = 配列[1、2、3] 変数B = 変数A # 変数Bに要素を追加 変数B.要素追加(4) # この時の変数Aは[1、2、3]のままか? ログ出力(変数A) ## -> 結果 ## JavaScript -> [1, 2, 3, 4] ## Python -> [1, 2, 3, 4] ## Swift -> [1, 2, 3]
- Swiftだけ
・・・どういうことだ、、、、と思い、調べた結果が続きです
結論と考察:
参考サイト
- https://www.zoma-blog.com/post/frontend/js/js_array_comparison/
- https://tech.anti-pattern.co.jp/javascriptde/
- https://qiita.com/koher/items/2a1a364de98845ac6963
実験結果と調べた結果のまとめ
-
配列の定義の仕方には「参照型(Reference Type)」と「値型(Value Type)」なるものがあるらしい
-
それと実験結果を対応させた表が以下の通り
JavaScript Python Swift 配列の型 参照型 参照型 値型 実験1結果 false True true 実験2結果 [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3] -
なるほど!だから実験1では、JavaScriptは定義した変数それぞれの配列のメモリ位置が違うから
false
になるし、Swiftは値を見てるからコピーされていてtrue
になるわけか ←わかる -
そして、実験2では、JavaScriptとPythonは参照渡ししてるから元の配列の要素も変わるし、Swiftは値渡しだから元の定義はさすがに変わらんか ←わかる
-
Pythonの配列は「参照型」でメモリ位置が違うはずなのに実験1が
True
←??
→どうやら、Pythonの配列は「参照型」なのだけど、比較の時にはちゃんと配列の要素と順番を持ってきてくれるらしい(知らんけど)
- →※記事にコメントいただきましたので加筆修正。Pythonの配列は「参照型」で間違いないが、
==
で比較すると値が同値かを判断し、is
で比較すると、メモリ位置であるid
が同値かを判断してくれるらしいです(下記の画像とリンク参照)。
最終的にわかったことまとめ
- JavaScriptの配列は参照型であり、比較演算子を使うときはメモリ位置を参照する
- Pythonの配列も参照型ではあるが、
比較演算子を使う時は配列の要素と順番を見てくれる比較演算子==
を使う時は配列の要素と順番を見てくれる。is
を使うと、メモリ位置を参照する。 - Swiftはそもそも配列が値型
以上です。