lollipop.onl

JavaScriptでundefindの使用が推奨されない理由

JavaScript
更新日:

TypeScript Deep Drive の見解

TypeScript Deep Drive という TypeScript のバイブル的リファレンスに次のようなページがあります。

TypeScript Deep Dive 日本語版 nullとundefined https://typescript-jp.gitbook.io/deep-dive/recap/null-undefined

このページでは undefined を値として使用するのを推奨していません

たとえば、値が undefined かどうかを調べるにはnullとの比較を推奨していたり、

TypeScript// 👎 Not good...
obj.prop === undefined
 
// 👍 Better
obj.prop == null

ルートレベルの変数が定義されているかを判断するには typeof の使用を推奨していたりします。

TypeScript// 👎 Not good...
globalObj === undefined
 
// 👍 Better
typeof globalObj === 'undefined'

ただ、Deep Driveにはundefinedを使用するべきではない具体的な理由が書かれていません。

ESLintルールの見解

代わりにESLintのno-undefinedルールのドキュメントを見ると、その理由が書かれていました。

undefinedは代入可能なグローバルオブジェクトのプロパティです。ECMAScript 3では undefinedを上書きすることができます。ECMAScriptではグローバルのundefinedを上書きできなくなりましたが(代入はできる)、スコープ変数としてundefinedをシャドーウィングすることができます。
https://eslint.org/docs/rules/no-undefined

つまり、undefinedは代入可能な変数なため、実装によってはundefinedに値が割り当てられることがあるようです。

TypeScript// ES3
// グローバルな undefined を上書き
window.undefined = 1;
 
var obj = {};
 
obj.prop === undefined; // false
TypeScript// ES5
// foo() 内の undefined を上書き
const foo = () => {
  const undefined = 1;
   
  var obj = {};
    
  obj.prop === undefined; // false
};

no-undefinedルールではundefinedに関するスタイルガイドを次のようにしています。

  • undefinedは初期化されていない変数にのみ使用する
  • 値がundefinedかどうかの判定はtypeof演算子を使用する

また、再代入・シャドーウィングによるundefinedの上書きはno-global-assignルールおよびno-shadow-restricted-namesルールを使用することで回避することもできます。

ESLint - Pluggable JavaScript linter no-global-assign - Rules https://eslint.org/docs/rules/no-global-assign

ESLint - Pluggable JavaScript linter no-shadow-restricted-names - Rules https://eslint.org/docs/rules/no-shadow-restricted-names

なお、no-undefinedルールはrecommendedを始めとしてairbnbstandardgoogleいずれのプリセットでも有効化されていません。

編集