この記事は何の記事?
Python と JavaScript で動きが違う点・同じ点をまとめた記事です
違う点・同じ点なんていくらでもあると思いますが,
個人的に痛い目を見た事例について取り上げていきます
他にこんなのもあるよなどあれば是非教えていただきたいです
では本編スタートです
変数のスコープ・宣言・代入
Python の場合,宣言だけするということはできなく,
代入したときに変数が作られます
www.w3schools.com
hensu = "あたい" # これだけ
JavaScript の場合,宣言と代入はそれぞれ分けられます
// 宣言と代入一緒に
let hensu = "あたい"
// 宣言と代入をわけて
let sengen
sengen = "せんげん"
ということで例を見ていきます
以下の流れを確認します
- 変数
hensu
を出力する(1 回目) - 変数
hensu
に値を代入する関数kansu
を呼び出す - 変数
hensu
を出力する(2 回目)
まず Python の例です
1 回目, 2 回目共に xx
が出力されます
関数の外にある変数 hensu
と,
関数 kansu
内の変数 hensu
は,スコープが異なるので名前が同じな別の子
よって関数の外にある変数 hensu
には "ww"
は代入されていません
# 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 の挙動
let hensu = "xx" // 関数の外にある hensu
function kansu() {
hensu = "ww" // 関数の外にある hensu と同じ子
}
console.log(hensu) // xx
kansu()
console.log(hensu) // ww
因みに上記の JavaScript の挙動は,
Python でいうところの,global
を使った時と同じ挙動になります
# 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 の挙動
# 定義にいない引数を使う
def arg_nothing():
print("arg_nothing が呼び出されました")
arg_nothing(123)
# TypeError: arg_nothing() takes 0 positional arguments but 1 was given
引数 0 個のはずなのに 1 個引数が与えられたよっていうエラーがでます
# 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 の挙動
# 定義より引数の数が多い
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 の挙動
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 の例
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 の例
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 で確認
print(self)
# NameError: name 'self' is not defined
Python の場合,self
?知らない子ですねと言われます
// JavaScript で確認
console.log(this)
// Window {window: Window, self: Window, document: document, name: '', location: Location, …}
JavaScript の場合,Window
オブジェクトが表示されます
とここまでは良いのですが,
大きな違いとして,JavaScript には関数を作る方法が大きく分けて,
関数宣言と関数式があり,更に関数式には普通の関数式とアロー関数があります
これの何が問題かというと,メソッド呼び出しと関数呼び出しの時,
this
の値が普通の関数式かアロー関数かで異なるという点です
詳しくはこちらの記事が参考になります
https://jsprimer.net/basic/function-this/