+)== と ===== と !=)=== と !==)=== よりもさらに厳密: Object.is()JavaScript の演算子は奇妙に見えるかもしれません。次の 2 つのルールを理解すれば、より簡単に理解できます。
演算子が適切な型ではないオペランドを受け取った場合、例外をスローすることはまれです。代わりに、演算を実行できるように、オペランドを*強制変換*(自動的に変換)します。 2 つの例を見てみましょう。
まず、乗算演算子は数値でのみ動作します。したがって、結果を計算する前に文字列を数値に変換します。
> '7' * '3'
21次に、オブジェクトのプロパティにアクセスするための角括弧演算子 ([ ]) は、文字列とシンボルのみを処理できます。他のすべての値は文字列に強制変換されます。
const obj = {};
obj['true'] = 123;
// Coerce true to the string 'true'
assert.equal(obj[true], 123);前述のように、ほとんどの演算子はプリミティブ値でのみ動作します。オペランドがオブジェクトの場合、通常はプリミティブ値に強制変換されます。例:
> [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 + true
5Number(true) は 1 です。
単純代入演算子は、ストレージの場所を変更するために使用されます。
x = value; // assign to a previously declared variable
obj.propKey = value; // assign to a property
arr[index] = value; // assign to an Array element変数宣言のイニシャライザも代入の一種と見なすことができます。
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 = '';
str += '<b>';
str += 'Hello!';
str += '</b>';
assert.equal(str, '<b>Hello!</b>');== と ===JavaScript には、緩い等価性 (==) と厳密な等価性 (===) の 2 種類の等価演算子があります。常に後者を使用することをお勧めします。
== と === の他の名前
== は*ダブルイコール*とも呼ばれます。言語仕様における公式名は、抽象的な等価比較です。=== は*トリプルイコール*とも呼ばれます。== と !=)緩い等価性は、JavaScript の癖の 1 つです。多くの場合、オペランドを強制変換します。これらの強制変換の一部は意味をなします。
> '123' == 123
true
> false == 0
trueそうでないものもあります。
> '' == 0
trueオブジェクトは、他のオペランドがプリミティブの場合(そしてその場合にのみ!)、プリミティブに強制変換されます。
> [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 == arr
true最後に、== は undefined と null が等しいと見なします。
> undefined == null
true=== と !==)厳密な等価性は決して強制変換しません。2 つの値は、型が同じである場合にのみ等しくなります。以前の == 演算子とのやり取りを再検討し、=== 演算子が何をするかを見てみましょう。
> false === 0
false
> '123' === 123
falseオブジェクトは、その値が同じオブジェクトである場合にのみ、他の値と等しくなります。
> [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 === arr
true=== 演算子は、undefined と null が等しいとは見なしません。
> undefined === null
false常に === を使用することをお勧めします。これにより、コードが理解しやすくなり、== の癖について考える必要がなくなります。
== の 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 === NaN
falseそれは時々役に立ちます。たとえば、それを使用して、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 >= 2
true
> 'bar' < 'foo'
true<= と >= は、厳密な等価性に基づいています。
順序演算子は人間の言語ではうまく機能しません
順序演算子は、大文字と小文字の区別やアクセント記号が含まれる場合など、人間の言語でテキストを比較するのには適していません。詳細については、§20.6 「文字列の比較」で説明します。
次の演算子については、本書の別の場所で説明します。
次の 2 つのサブセクションでは、めったに使用されない 2 つの演算子について説明します。
カンマ演算子は 2 つのオペランドを持ち、両方を評価して 2 番目のオペランドを返します。
> 'a', 'b'
'b'この演算子の詳細については、Speaking JavaScript を参照してください。
void 演算子void 演算子は、オペランドを評価して undefined を返します。
> void (3 + 2)
undefinedこの演算子の詳細については、Speaking JavaScript を参照してください。
クイズ
クイズアプリを参照してください。