◆ try-catch 系の処理でエラー時に受け取った値の変数はどこまで有効なのか
◆ JavaScript と Python では catch/except のブロックの中だけ有効
◆ PHP と Ruby は catch/rescue を抜けても有効

これまであまり気にしたことがなかったのですが REPL 上でコードを書いていてふと気になりました

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 の内外関係なく参照できます