undefined
と null
undefined
vs. null
undefined
と null
の出現undefined
の出現null
の出現undefined
または null
のチェック??
)[ES2020]||
)の利用??=
)[ES2021]undefined
と null
はプロパティを持たないundefined
と null
の歴史多くのプログラミング言語には、null
という1つの「非値」があります。これは、変数が現在オブジェクトを指していないことを示します。たとえば、まだ初期化されていない場合などです。
対照的に、JavaScriptには2つあります。undefined
と null
です。
undefined
vs. null
両方の値は非常に似ており、しばしば互換的に使用されます。したがって、それらの違いは微妙です。言語自体は、次の区別をしています。
undefined
は「初期化されていない」(変数など)または「存在しない」(オブジェクトのプロパティなど)ことを意味します。null
は「任意のオブジェクト値の意図的な欠落」(言語仕様からの引用)を意味します。プログラマーは次の区別をするかもしれません。
undefined
は、(何かが初期化されていない場合などに)言語によって使用される非値です。null
は「明示的にオフにされた」ことを意味します。つまり、意味のある値と「意味のある値がない」ことを表すメタ値の両方を含む型を実装するのに役立ちます。このような型は、関数型プログラミングではオプション型またはMaybe型と呼ばれます。undefined
と null
の出現次のサブセクションでは、言語内で undefined
と null
がどこに出現するかについて説明します。この本で後ほど詳しく説明するいくつかのメカニズムに出会うことになります。
undefined
の出現未初期化の変数 myVar
let myVar;
.equal(myVar, undefined); assert
パラメータ x
が指定されていない
function func(x) {
return x;
}.equal(func(), undefined); assert
プロパティ .unknownProp
が見つからない
const obj = {};
.equal(obj.unknownProp, undefined); assert
return
ステートメントを介して関数の結果を明示的に指定しない場合、JavaScriptは undefined
を返します。
function func() {}
.equal(func(), undefined); assert
null
の出現オブジェクトのプロトタイプは、オブジェクトであるか、プロトタイプチェーンの最後では null
です。Object.prototype
にはプロトタイプがありません。
> Object.getPrototypeOf(Object.prototype)null
正規表現(/a/
など)を文字列('x'
など)に対してマッチングする場合、マッチングが成功した場合はマッチングデータを含むオブジェクトが得られるか、マッチングが失敗した場合は null
が得られます。
> /a/.exec('x')null
JSONデータ形式は、undefined
をサポートしておらず、null
のみサポートしています。
> JSON.stringify({a: undefined, b: null})'{"b":null}'
undefined
または null
のチェックどちらかのチェック
if (x === null) ···
if (x === undefined) ···
x
は値を持っていますか?
if (x !== undefined && x !== null) {
// ···
}if (x) { // truthy?
// x is neither: undefined, null, false, 0, NaN, ''
}
x
は undefined
または null
のどちらかですか?
if (x === undefined || x === null) {
// ···
}if (!x) { // falsy?
// x is: undefined, null, false, 0, NaN, ''
}
Truthy は「ブール値に強制変換された場合に true
になる」ことを意味します。Falsy は「ブール値に強制変換された場合に false
になる」ことを意味します。両方の概念は、§15.2「Falsyとtruthyな値」で適切に説明されています。
??
)[ES2020]値を受け取って、それが null
または undefined
のどちらでもない場合にのみ使用したい場合があります。それ以外の場合は、フォールバックとしてデフォルト値を使用したいと思います。これは、Nullish coalescing演算子(??
)を使用して行うことができます。
const valueToUse = receivedValue ?? defaultValue;
次の2つの式は同等です。
?? b
a !== undefined && a !== null ? a : b a
次のコードは、実世界の例を示しています。
function countMatches(regex, str) {
const matchResult = str.match(regex); // null or Array
return (matchResult ?? []).length;
}
.equal(
assertcountMatches(/a/g, 'ababa'), 3);
.equal(
assertcountMatches(/b/g, 'ababa'), 2);
.equal(
assertcountMatches(/x/g, 'ababa'), 0);
str
内に regex
の一致が1つ以上ある場合、.match()
は配列を返します。一致がない場合、残念ながら(空の配列ではなく)null
を返します。??
演算子を使用して修正します。
オプショナルチェイニングを使用することもできました。
return matchResult?.length ?? 0;
function getTitle(fileDesc) {
return fileDesc.title ?? '(Untitled)';
}
const files = [
path: 'index.html', title: 'Home'},
{path: 'tmp.html'},
{;
].deepEqual(
assert.map(f => getTitle(f)),
files'Home', '(Untitled)']); [
場合によっては、分割代入をデフォルト値に使用することもできます。たとえば、次のようになります。
function getTitle(fileDesc) {
const {title = '(Untitled)'} = fileDesc;
return title;
}
||
)の利用ECMAScript 2020以前およびNullish coalescing演算子以前は、論理ORがデフォルト値に使用されていました。これには欠点があります。
||
は undefined
および null
に対して期待どおりに動作します。
> undefined || 'default''default'
> null || 'default''default'
しかし、他のすべてのfalsyな値に対してもデフォルトを返します。たとえば、次のようになります。
> false || 'default''default'
> 0 || 'default''default'
> 0n || 'default''default'
> '' || 'default''default'
それを ??
の動作と比較してください。
> undefined ?? 'default''default'
> null ?? 'default''default'
> false ?? 'default'false
> 0 ?? 'default'0
> 0n ?? 'default'0n
> '' ?? 'default'''
??=
)[ES2021]??=
は論理代入演算子です。次の2つの式はほぼ同等です。
??= b
a ?? (a = b) a
つまり、??=
はショートサーキットです。代入は、a
が undefined
または null
の場合にのみ行われます。
??=
を使用して欠落しているプロパティを追加するconst books = [
{isbn: '123',
,
}
{title: 'ECMAScript Language Specification',
isbn: '456',
,
};
]
// Add property .title where it’s missing
for (const book of books) {
.title ??= '(Untitled)';
book
}
.deepEqual(
assert,
books
[
{isbn: '123',
title: '(Untitled)',
,
}
{title: 'ECMAScript Language Specification',
isbn: '456',
,
}; ])
undefined
と null
はプロパティを持たないundefined
と null
は、プロパティを読み取ろうとした場合に例外が発生する唯一の2つのJavaScriptの値です。この現象を調べるために、プロパティ .foo
を読み取って(「取得」して)結果を返す次の関数を使用しましょう。
function getFoo(x) {
return x.foo;
}
getFoo()
をさまざまな値に適用すると、undefined
と null
の場合にのみ失敗することがわかります。
> getFoo(undefined)TypeError: Cannot read properties of undefined (reading 'foo')
> getFoo(null)TypeError: Cannot read properties of null (reading 'foo')
> getFoo(true)undefined
> getFoo({})undefined
undefined
と null
の歴史(JavaScriptの多くの側面に影響を与えた)Javaでは、初期化値は変数の静的な型に依存します。
null
で初期化されます。int
変数は 0
で初期化されます。JavaScriptでは、各変数はオブジェクト値とプリミティブ値の両方を保持できます。したがって、null
が「オブジェクトではない」ことを意味する場合、JavaScriptには「オブジェクトでもプリミティブ値でもない」ことを意味する初期化値も必要です。その初期化値が undefined
です。
クイズ
クイズアプリを参照してください。