+
)==
と ===
==
と !=
)===
と !==
)===
よりもさらに厳密: Object.is()
JavaScript の演算子は奇妙に見えるかもしれません。次の 2 つのルールを理解すれば、より簡単に理解できます。
演算子が適切な型ではないオペランドを受け取った場合、例外をスローすることはまれです。代わりに、演算を実行できるように、オペランドを*強制変換*(自動的に変換)します。 2 つの例を見てみましょう。
まず、乗算演算子は数値でのみ動作します。したがって、結果を計算する前に文字列を数値に変換します。
> '7' * '3'21
次に、オブジェクトのプロパティにアクセスするための角括弧演算子 ([ ]
) は、文字列とシンボルのみを処理できます。他のすべての値は文字列に強制変換されます。
const obj = {};
'true'] = 123;
obj[
// Coerce true to the string 'true'
.equal(obj[true], 123); assert
前述のように、ほとんどの演算子はプリミティブ値でのみ動作します。オペランドがオブジェクトの場合、通常はプリミティブ値に強制変換されます。例:
> [1,2,3] + [4,5,6]'1,2,34,5,6'
なぜでしょうか?プラス演算子は、まずオペランドをプリミティブ値に強制変換します。
> String([1,2,3])'1,2,3'
> String([4,5,6])'4,5,6'
次に、2 つの文字列を連結します。
> '1,2,3' + '4,5,6''1,2,34,5,6'
+
)JavaScript のプラス演算子は次のように動作します。
文字列モードでは、+
を使用して文字列を組み立てることができます。
> 'There are ' + 3 + ' items''There are 3 items'
数値モードでは、オペランドのいずれも文字列(または文字列になるオブジェクト)でない場合、すべてが数値に強制変換されることを意味します。
> 4 + true5
Number(true)
は 1
です。
単純代入演算子は、ストレージの場所を変更するために使用されます。
= value; // assign to a previously declared variable
x .propKey = value; // assign to a property
obj= value; // assign to an Array element arr[index]
変数宣言のイニシャライザも代入の一種と見なすことができます。
const x = value;
let y = value;
JavaScript は次の代入演算子をサポートしています。
+= -= *= /= %=
[ES1]+=
は文字列連結にも使用できます。**=
[ES2016]&= ^= |=
[ES1]<<= >>= >>>=
[ES1]||= &&= ??=
[ES2021]論理代入演算子は、他の複合代入演算子とは異なる動作をします。
代入演算子 | 同等のもの | a がの場合のみ代入 |
---|---|---|
a ||= b |
a || (a = b) |
Falsy (偽) |
a &&= b |
a && (a = b) |
Truthy (真) |
a ??= b |
a ?? (a = b) |
Nullish (nullish) |
a ||= b
が次の式と同等なのはなぜですか?
a || (a = b)
なぜ次の式ではないのですか?
a = a || b
前の式には短絡評価の利点があります。代入は、a
が false
と評価された場合にのみ評価されます。したがって、代入は必要な場合にのみ実行されます。対照的に、後者の式は常に代入を実行します。
??=
の詳細については、§14.4.5 「nullish 合体代入演算子 (??=
) [ES2021]」を参照してください。
|| && ??
以外の演算子 op
の場合、次の 2 つの代入方法は同等です。
myvar op= value
myvar = myvar op value
たとえば、op
が +
の場合、次のように動作する演算子 +=
が得られます。
let str = '';
+= '<b>';
str += 'Hello!';
str += '</b>';
str
.equal(str, '<b>Hello!</b>'); assert
==
と ===
JavaScript には、緩い等価性 (==
) と厳密な等価性 (===
) の 2 種類の等価演算子があります。常に後者を使用することをお勧めします。
==
と ===
の他の名前
==
は*ダブルイコール*とも呼ばれます。言語仕様における公式名は、抽象的な等価比較です。===
は*トリプルイコール*とも呼ばれます。==
と !=
)緩い等価性は、JavaScript の癖の 1 つです。多くの場合、オペランドを強制変換します。これらの強制変換の一部は意味をなします。
> '123' == 123true
> false == 0true
そうでないものもあります。
> '' == 0true
オブジェクトは、他のオペランドがプリミティブの場合(そしてその場合にのみ!)、プリミティブに強制変換されます。
> [1, 2, 3] == '1,2,3'true
> ['1', '2', '3'] == '1,2,3'true
両方のオペランドがオブジェクトの場合、それらが同じオブジェクトである場合にのみ等しくなります。
> [1, 2, 3] == ['1', '2', '3']false
> [1, 2, 3] == [1, 2, 3]false
> const arr = [1, 2, 3];
> arr == arrtrue
最後に、==
は undefined
と null
が等しいと見なします。
> undefined == nulltrue
===
と !==
)厳密な等価性は決して強制変換しません。2 つの値は、型が同じである場合にのみ等しくなります。以前の ==
演算子とのやり取りを再検討し、===
演算子が何をするかを見てみましょう。
> false === 0false
> '123' === 123false
オブジェクトは、その値が同じオブジェクトである場合にのみ、他の値と等しくなります。
> [1, 2, 3] === '1,2,3'false
> ['1', '2', '3'] === '1,2,3'false
> [1, 2, 3] === ['1', '2', '3']false
> [1, 2, 3] === [1, 2, 3]false
> const arr = [1, 2, 3];
> arr === arrtrue
===
演算子は、undefined
と null
が等しいとは見なしません。
> undefined === nullfalse
常に ===
を使用することをお勧めします。これにより、コードが理解しやすくなり、==
の癖について考える必要がなくなります。
==
の 2 つのユースケースと、代わりに推奨することを見てみましょう。
==
のユースケース: 数値または文字列との比較==
を使用すると、値 x
が数値であるか、文字列としての数値であるかを 1 回の比較で確認できます。
if (x == 123) {
// x is either 123 or '123'
}
次の 2 つの代替案のいずれかを推奨します。
if (x === 123 || x === '123') ···
if (Number(x) === 123) ···
最初に遭遇したときに、x
を数値に変換することもできます。
==
のユースケース: undefined
または null
との比較==
のもう 1 つのユースケースは、値 x
が undefined
または null
のいずれであるかを確認することです。
if (x == null) {
// x is either null or undefined
}
このコードの問題は、誰かがそのように書きたかったのか、それともタイプミスで === null
を意味したのかがわからないことです。
次の 2 つの代替案のいずれかを推奨します。
if (x === undefined || x === null) ···
if (!x) ···
2 番目の代替案の欠点は、undefined
と null
以外の値を受け入れることですが、これは JavaScript で確立されたパターンです(§15.3 「真偽値に基づく存在チェック」で詳細に説明します)。
次の 3 つの条件もほぼ同等です。
if (x != null) ···
if (x !== undefined && x !== null) ···
if (x) ···
===
よりもさらに厳密: Object.is()
メソッド Object.is()
は 2 つの値を比較します。
> Object.is(123, 123)true
> Object.is(123, '123')false
===
よりもさらに厳密です。たとえば、NaN
(数値を含む計算のエラー値) は、それ自身と等しいと見なします。
> Object.is(NaN, NaN)true
> NaN === NaNfalse
それは時々役に立ちます。たとえば、それを使用して、Array メソッド .indexOf()
の改良版を実装できます。
const myIndexOf = (arr, elem) => {
return arr.findIndex(x => Object.is(x, elem));
; }
myIndexOf()
は配列内で NaN
を見つけますが、.indexOf()
は見つけません。
> myIndexOf([0,NaN,2], NaN)1
> [0,NaN,2].indexOf(NaN)-1
結果 -1
は、.indexOf()
が配列内で引数を見つけることができなかったことを意味します。
演算子 | 名前 |
---|---|
< |
より小さい |
<= |
以下 |
> |
より大きい |
>= |
以上 |
JavaScript の順序演算子 (表3) は、数値と文字列の両方で動作します。
> 5 >= 2true
> 'bar' < 'foo'true
<=
と >=
は、厳密な等価性に基づいています。
順序演算子は人間の言語ではうまく機能しません
順序演算子は、大文字と小文字の区別やアクセント記号が含まれる場合など、人間の言語でテキストを比較するのには適していません。詳細については、§20.6 「文字列の比較」で説明します。
次の演算子については、本書の別の場所で説明します。
次の 2 つのサブセクションでは、めったに使用されない 2 つの演算子について説明します。
カンマ演算子は 2 つのオペランドを持ち、両方を評価して 2 番目のオペランドを返します。
> 'a', 'b''b'
この演算子の詳細については、Speaking JavaScript を参照してください。
void
演算子void
演算子は、オペランドを評価して undefined
を返します。
> void (3 + 2)undefined
この演算子の詳細については、Speaking JavaScript を参照してください。
クイズ
クイズアプリを参照してください。