catch した変数のスコープ
◆ try-catch 系の処理でエラー時に受け取った値の変数はどこまで有効なのか
◆ JavaScript と Python では catch/except のブロックの中だけ有効
◆ PHP と Ruby は catch/rescue を抜けても有効
◆ JavaScript と Python では catch/except のブロックの中だけ有効
◆ PHP と Ruby は catch/rescue を抜けても有効
これまであまり気にしたことがなかったのですが REPL 上でコードを書いていてふと気になりました
try-catch を使ったときに catch 句で受け取る変数ってどんなスコープなのでしょうか
言語による違いもありそうですが 気になったきっかけは JavaScript なのでまずは JavaScript についてです
JavaScript は 元々はブロックスコープではない言語です
var で変数宣言して関数がスコープになります
ただ catch の場合は var を使わない特殊なものです
catch でスコープが作られてないなら関数など親のスコープになっていて try-catch の外側でも参照できるはずです
互換性的に let/const が出てきてからも このスコープは変更されないと思うので もしかしたら try-catch の外でもエラーを参照できたりするのでしょうか
他言語も含めて試してみようと思います
発生させるエラーのメッセージが error だとパッと見て内部のエラーなのかが分かりづらいのでエラーメッセージは「えらー」にしてます
err が未定義なのでブロックスコープになっているようです
昔からこうでしたっけ?
気になったので ES2015 対応前の古い Node.js (0.10) と IE11 でも試してみました
それらでも同じで err 変数は try-catch の外側では参照できませんでした
昔から catch で受け取る値の変数はブロックスコープだったようです
Python は今でもブロックスコープではないのですが except 句で受け取った変数はブロックスコープで except の中でだけ使えるようです
PHP では catch でスコープは発生せず catch を抜けても参照できました
Ruby も PHP と同じで rescue を抜けても参照できました
他のスクリプト言語だと
Lua は try-catch の構文がありません
PowerShell では catch で指定できるのは例外の種類だけで受け取る変数名を指定できません
グローバル変数の $_ や $error[0] からエラーを取得することになります
グローバルなので catch の内外関係なく参照できます
try {
//
} catch (err) {
// 変数 err のスコープは?
}
try-catch を使ったときに catch 句で受け取る変数ってどんなスコープなのでしょうか
言語による違いもありそうですが 気になったきっかけは JavaScript なのでまずは JavaScript についてです
JavaScript は 元々はブロックスコープではない言語です
var で変数宣言して関数がスコープになります
ただ catch の場合は var を使わない特殊なものです
catch でスコープが作られてないなら関数など親のスコープになっていて try-catch の外側でも参照できるはずです
互換性的に let/const が出てきてからも このスコープは変更されないと思うので もしかしたら try-catch の外でもエラーを参照できたりするのでしょうか
他言語も含めて試してみようと思います
発生させるエラーのメッセージが error だとパッと見て内部のエラーなのかが分かりづらいのでエラーメッセージは「えらー」にしてます
catch の変数のスコープ
JavaScript
try {
throw new Error("えらー")
} catch (err) {
}
console.log(err)
ReferenceError: err is not defined
err が未定義なのでブロックスコープになっているようです
昔からこうでしたっけ?
気になったので ES2015 対応前の古い Node.js (0.10) と IE11 でも試してみました
それらでも同じで err 変数は try-catch の外側では参照できませんでした
昔から catch で受け取る値の変数はブロックスコープだったようです
Python
try:
raise Exception("えらー")
except Exception as err:
pass
print(err)
NameError: name 'err' is not defined
Python は今でもブロックスコープではないのですが except 句で受け取った変数はブロックスコープで except の中でだけ使えるようです
PHP
<?php
try {
throw new Exception("えらー");
} catch (Exception $err) {
}
var_dump($err);
object(Exception)#1 (7) {
["message":protected]=>
string(9) "えらー"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(10) "/opt/p.php"
["line":protected]=>
int(4)
["trace":"Exception":private]=>
array(0) {
}
["previous":"Exception":private]=>
NULL
}
PHP では catch でスコープは発生せず catch を抜けても参照できました
Ruby
begin
raise "えらー"
rescue => err
end
p err
#<RuntimeError: えらー>
Ruby も PHP と同じで rescue を抜けても参照できました
その他
静的言語は基本デフォルトでブロックスコープなので省略します他のスクリプト言語だと
Lua は try-catch の構文がありません
PowerShell では catch で指定できるのは例外の種類だけで受け取る変数名を指定できません
グローバル変数の $_ や $error[0] からエラーを取得することになります
グローバルなので catch の内外関係なく参照できます