演算子(えんざんし、operator)とは、2 + 3+のように、演算を表す記号のことです。2や3は被演算子(ひえんざんし、operandオペランド)といいます。JavaScriptには算術演算子以外にもさまざまな演算子があります。変数の代入で使用した=も演算子の一種ですし、コンマ,も演算子の一種です。 演算子はメソッドでは有りません。 演算子はメソッドと異なりオーバーロード出来ません。

算術演算子

編集

加算 (+)、減算 (-)、乗算 (*)、除算 (/) の四則演算をはじめとする基本的な算術演算子が存在します。数値は常に浮動小数点数として扱われます。 BigIntにも演算子を適用できますが、算術演算子の場合両方のオペランドがBigIntである必要があり異なる型が渡されると、暗黙の型変換は行われず TypeError となります。 数値の演算で NaN を返すケースは、BigIntではErrorとなります(例えばゼロ除算は数値ではNaNを返しますが、BigInt同士ではRangeErrorthrowされます)。

JavaScriptの算術演算子
演算子 意味
a + b 加算
a - b 減算
a * b 乗算
a / b 除算
a % b 剰余
a ** b べき乗
+a 単項プラス(数値化)
-a 単項マイナス(算術否定)
a++ または ++a インクリメント
a-- または --a デクリメント

加算演算子 (+)

編集

加算演算子(かさんえんざんし、addition operator)は+です[1]

変数twoを1+1で初期化するとtwoの値は2となる
const two = 1 + 1;
console.log(two);
実行結果
2

減算演算子 (-)

編集

減算演算子(げんざんえんざんし、げんさんえんざんし、subtraction operator)は-です[2]

変数minus_oneを0-1で初期化するとminus_oneの値は-1となる
const minus_one = 0 - 1;
console.log(minus_one);
実行結果
-1

乗算演算子 (*)

編集

乗算演算子(じょうざんえんざんし、じょうさんえんざんし、multiplication operator)は*です。

const four = 2 * 2; // 変数fourを2×2で初期化するとfourは4となる
console.log(four); // 4

除算演算子 (/)

編集

除算演算子(じょざんえんざんし、じょさんえんざんし、division operator)は/です。

const one_half = 1 / 2; // 変数one_halfを1÷2で初期化するとone_halfは0.5となる
console.log(one_half); // 0.5

ゼロ除算(ゼロじょざん、ゼロじょさん、division by zero)は例外ではなくInfinity(あるいは-Infinity)を返します。 BigInt 同士のゼロ除算は RangeError となります。

console.log( 1 / 0 ); // Infinity
console.log( -2 / 0 ); // -Infinity
console.log( 3 /-0 ); // -Infinity
console.log( -3 /-0 ); // Infinity
console.log( 1n / 0n ); // RangeError: Division by zero

除数・被除数ともゼロの除算はNaNを返します。 BigInt 同士の除数・被除数ともゼロの除算は RangeError となります。

console.log( 0 / 0 ); // NaN
console.log( 0n / 0n ); // RangeError: Division by zero

剰余演算子 (%)

編集

剰余演算子(じょうよえんざんし、REMAINDER operator)は%です。割り算の余りを求めます。

const one = 10 % 3; // 10÷3は3余り1なので変数oneは1となる
console.log(one); // 1

結果は必ず左オペランドの被除数(割られる数)と同じ符号になります。

const minus_one = -10 % 3;
console.log(minus_one); // -1

ゼロ剰余(ゼロじょうよ、REMAINDER by zero)は例外ではなくNaNを返します。 BigInt 同士の剰余は RangeError となります。

console.log( 10 % 0 ); // NaN
console.log( 10n % 0n ); // RangeError: Division by zero

a % ba - b * Math.trunc(a / b)と等価です。 Perl や Ruby のようにa - b * Math.floor(a / b)と等価ではありません。これは IEEE754 の Remainder に定義された挙動で C 言語の libm にある fmod() と同じ動作です。

const remainder = (a,b) => (a - b * Math.trunc(a/b));
for (let i = -1.2; i <= 1.2; i += 1.2)
  for (let j = -1.3; j <= 1.3; j += 1.3)
    console.log(`${i} % ${j}= ${i%j} (=${remainder(i,j)}), ${i} / ${j} = ${i / j}`);
/*
 -1.2 % -1.3= -1.2 (=-1.2), -1.2 / -1.3 = 0.923076923076923
 -1.2 % 0= NaN (=NaN), -1.2 / 0 = -Infinity
 -1.2 % 1.3= -1.2 (=-1.2), -1.2 / 1.3 = -0.923076923076923
 0 % -1.3= 0 (=0), 0 / -1.3 = 0
 0 % 0= NaN (=NaN), 0 / 0 = NaN
 0 % 1.3= 0 (=0), 0 / 1.3 = 0
 1.2 % -1.3= 1.2 (=1.2), 1.2 / -1.3 = -0.923076923076923
 1.2 % 0= NaN (=NaN), 1.2 / 0 = Infinity
 1.2 % 1.3= 1.2 (=1.2), 1.2 / 1.3 = 0.923076923076923
*/

除数は浮動小数点数でもかまいません(元々 Number は64ビット倍精度浮動小数点数です)。

const theta = Math.PI / 4;
console.log(Math.sin(theta) === Math.sin(theta % (2 * Math.PI))); // true

単項プラス演算子 +()

編集

単項プラス演算子(たんこうプラスえんざんし、unary plus operator)は式を評価し、数値でなかった場合は暗黙な変換に従い数値に変換します。

const two = "2";
console.log(+two); // 2

単項プラスと暗黙の型変換

編集
const ary = [undefined, null, false, true, 0, 1, "", "1", [], [2]]
const json = ary.map(x => x === undefined ? "undefined" : JSON.stringify(x))
let s = ""
s += `{| class="wikitable"
|+ 単項プラスと暗黙の型変換
! ${json.join("!!")}
`
  s += `|-
| ${ary.map(x => `${+x}:${typeof(+x)}` ).join("||")}
`
s += `|}`
console.log(s)
単項プラスと暗黙の型変換
undefined null false true 0 1 "" "1" [] [2]
NaN:number 0:number 0:number 1:number 0:number 1:number 0:number 1:number 0:number 2:number

単項マイナス演算子 -()

編集

単項マイナス演算子(たんこうマイナスえんざんし、unary negation operator)は符号を反転させた数(反数)を返します。符号反転演算子(ふごうはんてんえんざんし)、算術否定演算子(さんじゅつひていえんざんし)などという言い方をする人もいます。

const one = 1;
console.log(-one); // -1

a * -1と似ていますが BigInt が渡されても TypeError とはならない点が異なります。

インクリメント演算子 (++)

編集

インクリメント演算子(インクリメントえんざんし、increment operator)は変数の値を1増やします。

let x = 0;
x++;
console.log(x); // 1

インクリメント演算子は後置++すると増やす前の値を返し、

let x = 0;
const y = x++;
console.log(y); // 0
console.log(x); // 1

++前置すると増やした後の値を返します。

let x = 0;
const y = ++x;
console.log(y); // 1
console.log(x); // 1

複数のインクリメント演算子を同時に適用することはできません。

let x = 0;
(x++)++; // SyntaxError: Invalid left-hand side expression in postfix operation

x++x += 1、すなわちx = x + 1と等価です。インクリメント演算子は変数の値を増加させるので、1++のようにリテラル(定数)に対して適用することはできません。

デクリメント演算子 (--)

編集

デクリメント演算子(デクリメントえんざんし、decrement operator)は変数の値を1減らします。

let x = 0;
x--;
console.log(x); // -1

デクリメント演算子は後置--すると減らす前の値を返し、

let x = 0;
const y = x--;
console.log(y); // 0
console.log(x); // -1

--前置すると減らした後の値を返します。

let x = 0;
const y = --x;
console.log(y); // -1
console.log(x); // -1

複数のデクリメント演算子を同時に適用することはできません。

let x = 0;
(x--)--; // SyntaxError: Invalid left-hand side expression in postfix operation

x--x -= 1、すなわちx = x - 1と等価です。デクリメント演算子は変数の値を減少させるので、1--のようにリテラル(定数)に対して適用することはできません。

冪乗演算子 (**)

編集

冪乗演算子(べきじょうえんざんし)は、第1オペランドを第2オペランドの累乗した結果を返します。Math.pow と同等ですが、オペランドとして BigInt を受け入れることができます。

const power = 2 ** 10;
console.log(power); // 1024

なお、^はビットごとのXOR演算子です。

ビット演算子

編集

ビット演算子(ビットえんざんし、bitwise operator)は、ビット演算の演算子です。ビット演算とは数値を32ビット整数変換し、各ビットに対して行う演算のことです。

JavaScriptのビット演算子
演算子 意味
a & b ビットごとのAND
a | b ビットごとのOR
a ^ b ビットごとのXOR
~a ビットごとのNOT(補数)
a << b 左シフト
a >> b 右シフト
a >>> b 符号なし右シフト

a >>> bは捨てられたビットの分だけ左から0を詰めます。 ' >>> は BigInt に適用すると TypeError になります。 ビット演算子は算術演算子よりも優先順位が低いことに注意してください。

文字列連結演算子

編集

+は加算演算子であると同時に、文字列連結演算子(もじれつれんけつえんざんし、string concatenation operator)でもあります。

const str = "Wiki" + "books";
console.log(str); // "Wikibooks"

文字列と数値を連結すると、文字列の方が強いので数値は文字列に変換されます。

const str = "JavaScript " + 1.5;
console.log(str); // "JavaScript 1.5"

これは足し算をしようとして文字列がまじっていると厄介なことになります。

const one = "1";
const two = one + 1;
console.log(two); // "11" -- console.log()メソッドではわかりにくいですが、2文字の文字列です。

文字列の連結よりも数値の加算を優先させるには、文字列を数値に変換した上で加算しなければなりません。文字列を数値に変換するには、教科書的にはparseInt関数やparseFloat関数、Numberオブジェクトのコンストラクタなどを使いますが、

const one = "1";
const two = parseInt(one) + 1;
console.log(two); // 2

一般的には単項プラス演算子を使用した方が高速です。

const one = "1";
const two = +one + 1;
console.log(two); // 2

ほかにも1を掛ける (one * 1)、0を引く (one - 0))などの方法があります。 これらの演算子は数値にしか適用できないので、処理系が被演算子を自動的に数値に変換(暗黙的な型変換)するためです。

かつてこの本で、0で符号なし右シフトをする (one >>> 0あるいは 補数の補数を得る(~~one)文字列を数値に変換する方法として紹介されていましたが、前者は32ビット符号なし整数に、後者は32ビット符号付き整数への変換となり浮動小数点数を表す文字列に適用すると、、

"3.14" >>> 0  === 3
"-3.14" >>> 0 === 4294967293
~~"3.14"  === 3
~~"-3.14" === -3

の様になります。興味深い挙動ですが文字列を数値に変換する方法としては妥当とは言えません。

加算と暗黙の型変換

編集

加算と暗黙の型変換の結果を表にしました。

const ary = [undefined, null, false, true, 0, 1, "", "1", [], [2]]
const json = ary.map(x => x === undefined ? "undefined" : JSON.stringify(x))
let s = ""
s += `{| class="wikitable"
|+ 加算と暗黙の型変換
! ${["左辺\右辺",...json].join("!!")}
`
for (const y of ary) {
  s += `|-
! ${y === undefined ? "undefined" : JSON.stringify(y)}
| ${ary.map(x => `${y + x}:${typeof(y + x)}` ).join("||")}
`
}
s += `|}`
console.log(s)
加算と暗黙の型変換
左辺\右辺 undefined null false true 0 1 "" "1" [] [2]
undefined NaN:number NaN:number NaN:number NaN:number NaN:number NaN:number undefined:string undefined1:string undefined:string undefined2:string
null NaN:number 0:number 0:number 1:number 0:number 1:number null:string null1:string null:string null2:string
false NaN:number 0:number 0:number 1:number 0:number 1:number false:string false1:string false:string false2:string
true NaN:number 1:number 1:number 2:number 1:number 2:number true:string true1:string true:string true2:string
0 NaN:number 0:number 0:number 1:number 0:number 1:number 0:string 01:string 0:string 02:string
1 NaN:number 1:number 1:number 2:number 1:number 2:number 1:string 11:string 1:string 12:string
"" undefined:string null:string false:string true:string 0:string 1:string :string 1:string :string 2:string
"1" 1undefined:string 1null:string 1false:string 1true:string 10:string 11:string 1:string 11:string 1:string 12:string
[] undefined:string null:string false:string true:string 0:string 1:string :string 1:string :string 2:string
[2] 2undefined:string 2null:string 2false:string 2true:string 20:string 21:string 2:string 21:string 2:string 22:string

この表は、二項演算子(+)と様々な値の組み合わせについて見てみました。

if文の条件式などのブーリアンコンテキストでの真理値への変換や、単項+の数値への変換は、また別の規則になります。

代入演算子

編集

代入演算子(だいにゅうえんざんし、assignment operator)は変数に値を代入します。代入した値を返し、結合は右から左です[3]

let x = 0;
console.log(x = 1); // 1

let a, b;
a = b = 0;

複合代入演算子

編集

複合代入演算子(ふくごうだいにゅうえんざんし、Compound assignment operators)は、x = x OPERATOR yの形式をx OPERATOR= yの形式に短縮表記したものです。代入演算子と同じ優先度を持ち、演算し代入した値を返し、結合は右から左です。OPERATORで1つのトークンで、OPERATOR=の間に空白を含めることはできません。 例えば、x *= yx = x * yと等価です。

let x = 1;
x += 1;   // x = x + 1
console.log(x); // 2
JavaScriptの代入演算子の短縮表記
短縮表記 等価な表記 意味
x += y x = x + y 加算代入演算子 (Addition assignment operator)
x -= y x = x - y 減算代入演算子 (Subtraction assignment operator)
x *= y x = x * y 乗算代入演算子 (Multiplication assignment operator)
x /= y x = x / y 除算代入演算子 (Division assignment operator)
x %= y x = x % y 剰余代入演算子 (Remainder assignment operator)
x **= y x = x ** y 冪乗代入演算子 (Exponentiation assignment operator)
x <<= y x = x << y 左シフト代入演算子 (Left shift assignment operator)
x >>= y x = x >> y 右シフト代入演算子 (Right shift assignment operator)
x >>>= y x = x >>> y 符号なし右シフト代入演算子 (Unsigned right shift assignment operator)
x &= y x = x & y ビット間論理積代入演算子 (Bitwise AND assignment operator)
x ^= y x = x ^ y ビット間排他的論理和代入演算子 (Bitwise XOR assignment operator)
x |= y x = x | y ビット間論理和代入演算子 (Bitwise OR assignment operator)
x &&= y x = x && y 論理積代入演算子 (Logical AND assignment operator)
x ||= y x = x || y 論理和代入演算子 (Logical OR assignment operator)
x ??= y x = x ?? y 論理Null合体代入演算子 (Logical nullish assignment operator)

分割代入

編集

分割代入(ぶんかつだいにゅう、Destructuring assignment)は、配列の値やオブジェクトのプロパティを個別の変数に展開することができるJavaScriptの表現方法です[4]

JavaScriptには、様々な種類の分割代入があります。以下に代表的なものを示します。

分割代入の例
// 配列の分割代入
const [a, b, c] = [1, 2, 3];
console.log(a); // => 1
console.log(b); // => 2
console.log(c); // => 3

// オブジェクトの分割代入
const person = { name: 'Alice', age: 20 };
const { name, age } = person;
console.log(name); // => 'Alice'
console.log(age); // => 20

// 別名の指定
const { name: firstName, age: years } = person;
console.log(firstName); // => 'Alice'
console.log(years); // => 20

// デフォルト値の指定
const { name: names  = 'Anonymous', age: ages = 0 } = {};
console.log(names); // => 'Anonymous'
console.log(ages); // => 0

// 関数の引数としての分割代入
function foo({ x, y }) {
  console.log(x, y);
}

const point = { x: 1, y: 2 };
foo(point); // => 1 2

// 可変長引数の受け取り
function sum(a, b, ...rest) {
  console.log(a + b);
  console.log(rest);
}

sum(1, 2, 3, 4, 5); 
// => 3
// => [3, 4, 5]
実行結果
1
2
3
Alice
20
Alice
20
Anonymous
0
1 2
3 
[ 3, 4, 5 ]

このコードは、JavaScriptにおける分割代入の様々な使い方を示しています。

最初の例では、配列の分割代入を使用して、3つの変数 abc にそれぞれ配列 [1, 2, 3] の要素を代入しています。

次に、オブジェクトの分割代入を使用して、オブジェクト person のプロパティ nameage を変数 nameage に代入しています。

その後、別名を指定してオブジェクトの分割代入を行い、変数 firstNameyearsperson オブジェクトのプロパティ nameage をそれぞれ代入しています。

次に、デフォルト値を指定してオブジェクトの分割代入を行い、空のオブジェクトから name プロパティが Anonymousage プロパティが 0 のデフォルト値を持つ変数 namesages を作成しています。

次に、関数の引数としての分割代入を示しています。 foo 関数は、オブジェクト { x, y } を引数として受け取り、そのプロパティを console.log で表示するように定義されています。この関数は、point オブジェクトを引数として呼び出され、その結果、1 2 が表示されます。

最後に、可変長引数を受け取る関数 sum を定義し、 12 を最初の2つの引数として、残りの引数を可変長引数 rest に代入しています。console.log を使用して、最初の2つの引数の合計値と残りの引数を表示します。sum(1, 2, 3, 4, 5) が呼び出されると、3[3, 4, 5] が表示されます。

論理演算子

編集

論理演算子(ろんりえんざんし、logical operator)とは、真偽値を返す論理的な演算子です。短絡評価副作用に注意してください[5]

論理積演算子 (&&)

編集

論理積演算子は、両方のオペランドが true であったら true を、それ以外は false を返します。

論理積演算子の構文

編集
left && right

論理和演算子 (||)

編集

論理和演算子は、片方または両方のオペランドが true であったら true を、それ以外は false を返します。

論理和演算子の構文

編集
left || right

否定演算子 (!)

編集

否定演算子は、オペランドを論理型に変換した後、true であったら false を、false であったら true を返します。

否定演算子の構文

編集
! bool

JavaScriptに排他的論理和演算子は存在しませんが、

  • Boolean(p) != Boolean(q)

と真偽値に変換した後、不一致を評価する式で実現できます。

  • !p != !q

でも可。

関係演算子

編集

関係演算子(かんけいえんざんし、Relational operator)とは、大小関係あるいは包含関係を比較して真偽値を返す演算子です[6]

[[../=<|=<]][[../=>|=>]] のようなに = が先にくる関係演算子は存在しないので気をつけてください(特に [[../=>|=>]] はアロー関数の構文で書き方によっては SyntaxError とならず発見困難なバグの原因になります)。大小比較は必ず手前に大なり小なり、後にイコールが来ます。

in 演算子

編集

in 演算子は、プロパティがオブジェクトに含まれると true を返します。for in 文の in とは違います。

in 演算子の構文

編集
prop in obj

instanceof 演算子

編集

instanceof 演算子は、コンストラクタのprototype プロパティがオブジェクトのプロトタイプ・チェーンのどこかに現れるかどうかをテストします。戻り値は、論理値です[7]

instanceof 演算子の構文

編集
obj1 instanceof obj2

小なり演算子

編集

小なり演算子は、左辺が右辺より小さいかどうかをテストします。戻り値は、論理値です。

小なり演算子の構文

編集
left < right

小なりイコール演算子

編集

小なりイコール演算子は、左辺が右辺より小さいあるいは等しいかをテストします。戻り値は、論理値です。

小なりイコール演算子の構文

編集
left <= right

大なり演算子

編集

大なり演算子は、左辺が右辺より大きいかどうかをテストします。戻り値は、論理値です。

大なり演算子の構文

編集
left > right

大なりイコール演算子

編集

大なりイコール演算子は、左辺が右辺より大きいあるいは等しいかをテストします。戻り値は、論理値です。

大なりイコール演算子の構文

編集
left >= right

等値演算子

編集

等値演算子(とうかえんざんし、equality operators)とは、比較して真偽値を返す演算子です[8]

等価演算子 (==)

編集

等価演算子は、左辺が右辺と等しいかをテストします。比較は暗黙の型変換の後に行われます。戻り値は、論理値です。

等価演算子の構文

編集
left == right

不等価演算子 (!=)

編集

不等価演算子は、左辺が右辺と等しくないかをテストします。比較は暗黙の型変換の後に行われます。戻り値は、論理値です。

不等価演算子の構文

編集
left != right

同値演算子 (===)

編集

同値演算子(厳密一致演算子)は、左辺が右辺と等しいかをテストします。型が異なれば直ちに不一致を返します。戻り値は、論理値です。N

同値演算子の構文

編集
left === right

不同値演算子 (!==)

編集

不同値演算子(厳密不一致演算子)は、左辺が右辺と等しくないかをテストします。型が異なれば直ちに不一致を返します。戻り値は、論理値です。

不同値演算子の構文

編集
left !== right
0と-0の比較
0 == -0;  // ES6 では true
0 === -0; // ES6 では true

ES6より前は 0 と -0 は一致しませんでしたが、ES6 以降は 0 と -0 は一致するようになりました。これは厳密一致についても同じです。

プロパティアクセサ

編集

プロパティアクセサproperty accessor)とは、オブジェクトの(メソッドを含む)プロパティにアクセスするための演算子式で、左辺値式です。

ドット記法のプロパティアクセサ

編集

ドット記法のプロパティアクセサは、object . propertyの構文で、.を挟んだ二項式です。 ドット記法では、propertyが識別子として有効なときにのみ使え、識別子以外を用いると SyntaxError を throw します。

const object = {};
object.myName = "tom"; // 正常
object.123 = 0; // SyntaxError: Invalid or unexpected token
object.my-name = "lisa"; // SyntaxError: Unexpected token '-'

ブラケット記法のプロパティアクセサ

編集

ブラケット記法のプロパティアクセサは、object [ property ]の構文で、[ ]を使った配列アクセス似の記法です。文字列の他、Symbol もキーにできます。

const object = {};
object["myName"] = "tom"; // 正常
object["123"] = 0; // 正常
object["my-name"] = "lisa"; // 正常

オプショナルチェイニング演算子(?.)

編集

オプショナルチェイニング演算子?.は、オブジェクトのプロパティへの安全なアクセスを可能にする演算子です。 対象のオブジェクトが null または undefined の場合、エラーを throw する代わりに undefined を返します。

const user = {
    address: {
        street: "Main St"
    }
};

console.log(user.address?.street); // "Main St"
console.log(user.contact?.phone); // undefined
// 従来の方法では以下のような冗長な書き方が必要でした
// console.log(user.contact && user.contact.phone);

Nullish合体演算子(??)

編集

Nullish合体演算子??は、左オペランドが null または undefined の場合にのみ、右オペランドを返す演算子です。 論理OR演算子(||||)と異なり、falsy な値(0false など)は代替値として扱いません。

const value = null;
const defaultValue = "デフォルト値";

console.log(value ?? defaultValue); // "デフォルト値"
console.log(0 ?? defaultValue); // 0 (0は保持される)
console.log("" ?? defaultValue); // "" (空文字列は保持される)

// オプショナルチェイニングと組み合わせた例
const user = {};
console.log(user.name ?? "名無しさん"); // "名無しさん"

これらの演算子を組み合わせることで、より安全で簡潔なコードを書くことができます。特にネストされたオブジェクトの操作や、デフォルト値の設定において有用です。

条件演算子

編集

条件が真なら式1を評価しその値を返す、条件が真でなければ式2を評価しその値を返します。

 条件 ? 式1 : 式2

カンマ演算子

編集

カンマで区切られた式を左から順に評価し、最後の式の値を返す

 式1, 式2, 式3, 式4, 式5 ...,式n

グループ化演算子

編集

グループ化演算子は、評価の優先順位を制御します。最上位の優先度を有しますが、短絡評価の影響を受けます[9]

 (  )

delete演算子

編集

delete演算子 はオブジェクトからプロパティを取り除きます。

delete プロパティ

関数呼び出し演算子

編集

関数名に続く括弧はグループ化演算子ではなく、関数呼び出しです。

 関数名 ( 引数列 )

new演算子

編集

new 演算子は、ユーザー定義のオブジェクト型や、コンストラクタ機能を持つ組み込みオブジェクト型のインスタンスを作成します[10]

new演算子の構文

編集
構文
 new コンストラクタ [ ( [ パラメータ列 ] ) ]
/*
 * function 製のコンストラクタに適用した例
 */
const T = function(x = 0) {
    this.x = x;
}
T.prototype.value = function() {
    return this.x;
}

const t = new T(42);
console.log(t.value())

/*
 * class に適用した例
 */
class C {
    constructor(x = 0) {
        this.x = x;
    }
    value() {
        return this.x;
    }
}

const c = new C(13);
console.log(c.value())
実行結果
42 
13

void 演算子

編集

式を評価し(結果に関わらず)undefined を返します。

 void 

yield 演算子

編集

yieldキーワードは、ジェネレータ機能(function*)を一時停止および再開するために使用します[11]

 yeild 

yield* 演算子

編集

yield*式は、別のジェネレータやイテレート可能なオブジェクトに処理を委譲します[12]

 yeild* 

typeof 演算子

編集

typeof演算子(タイプオブえんざんし、typeof operator)はデータ型を返します。

 typeof 
typeof 42;              // "number"
typeof "Hello, world!"; // "string"
typeof [1,2,3];         // "object"; Arrayラッパーオブジェクト
typeof new Array();     // "object"; Arrayラッパーオブジェクト
typeof new String("ab");// "object"; Stringラッパーオブジェクト
typeof new RegExp();    // "object"; RegExpラッパーオブジェクト
typeof new Set();       // "object"; Setラッパーオブジェクト
typeof new WeakSet();   // "object"; WeakSetラッパーオブジェクト
typeof new Map();       // "object"; Mapラッパーオブジェクト
typeof new WeakMap();   // "object"; WeakMapラッパーオブジェクト
typeof function(){};    // "function"
typeof true;            // "boolean"
typeof void 0;          // "undefined"
typeof null;            // "object"; ラッパーではなく互換性のための仕様
typeof 123n;            // "bigint"
typeof Symbol();        // "symbol"
typeof {};              // "object"

結合性

編集

同じ優先順位の演算子(下表参照)が連なった時の評価順序を結合性(けつごうせい、associativity)といいます。

左結合(ひだりけつごう、left-associative)
左から右に評価される演算
( expr1 OP1 expr2 ) OP2 expr3と解釈される
典型的には四則
右結合(みぎけつごう、right-associative)
右から左に評価される演算
expr1 OP1 ( expr2 OP2 expr3 )と解釈される
典型的には代入

たとえば、a - b - ca - (b - c)ではなく(a - b) - cと左から右に評価されるため、減算演算子は左結合です。また、a = b = c(a = b) = cではなくa = (b = c)と評価されるため、代入演算子は右結合です。インクリメント演算子++やデクリメント演算子--は、左辺値式ではないので x++ ++ とすると SyntaxErroor となり結合性は定義されません。

結合性の例題

編集

次の式の演算子の結合性を述べ、それに従い括弧を補ってください。

  1. typeof typeof object
  2. p == q == r
  3. a > 0 ? 1 : a < 0 ? -1 : 0
  4. a, b, c


結合性の例題の解答

編集
  1. 右結合:typeof ( typeof object )と解釈されます。
  2. 左結合:p == q == r( p == q ) == rと解釈されます。
  3. 右結合:a > 0 ? 1 : ( a < 0 ? -1 : 0 )と解釈される[13]
  4. 左結合:( a, b ), cと解釈されます(式の値は、c となります)。

演算子の優先順位

編集
JavaScriptの演算子の優先順位と結合性[14]
優先順位 シンボル カテゴリ 結合性 構文 解説
20 () グループ化 なし (expression) 式の評価順序を明示的に指定します。
19 . メンバーアクセス 左から右 object.property オブジェクトのプロパティにアクセスします。
19 [] メンバーアクセス 左から右 object[expression] オブジェクトのプロパティに計算されたキーでアクセスします。
19 ?. オプショナルチェイニング 左から右 object?.property 左辺がnullまたはundefinedの場合、評価を停止してundefinedを返します。
19 ?.[] オプショナルチェイニング 左から右 object?.[expression] 左辺がnullまたはundefinedの場合、評価を停止してundefinedを返します。
19 new オブジェクト生成 なし new Constructor(arguments) コンストラクタを使用して新しいオブジェクトを作成します。
19 new オブジェクト生成 なし new Constructor 引数なしでコンストラクタを呼び出します。
19 () 関数呼び出し 左から右 function(arguments) 関数を実行します。
19 ?.() オプショナル関数呼び出し 左から右 function?.(arguments) 左辺が呼び出し可能な場合のみ関数を実行します。
18 ++ (後置) 更新 なし variable++ 変数の現在の値を返した後、値を1増加させます。
18 -- (後置) 更新 なし variable-- 変数の現在の値を返した後、値を1減少させます。
17 ! 論理 右から左 !expression 論理否定(真偽値を反転)
17 ~ ビット 右から左 ~expression ビット否定(ビットを反転)
17 + (単項) 単項 右から左 +expression 単項オペランドを数値に変換します。
17 - (単項) 単項 右から左 -expression 単項オペランドを数値に変換し、符号を反転します。
17 ++ (前置) 更新 右から左 ++variable 変数の値を1増加させた後、その値を返します。
17 -- (前置) 更新 右から左 --variable 変数の値を1減少させた後、その値を返します。
17 typeof 単項 右から左 typeof expression 単項オペランドの型を表す文字列を返します。
17 void 単項 右から左 void expression 単項式を評価し、undefinedを返します。
17 delete 単項 右から左 delete object.property オブジェクトのプロパティを削除します。
17 await 単項 右から左 await promise Promise が解決または拒否されるまで待機します。
16 ** 算術 右から左 base ** exponent べき乗(指数)
15 * 算術 左から右 operand1 * operand2 乗算
15 / 算術 左から右 operand1 / operand2 除算
15 % 算術 左から右 operand1 % operand2 剰余(余り)
14 + 算術/文字列 左から右 operand1 + operand2 加算または文字列連結
14 - 算術 左から右 operand1 - operand2 減算
13 << ビットシフト 左から右 operand1 << operand2 左シフト
13 >> ビットシフト 左から右 operand1 >> operand2 符号付き右シフト
13 >>> ビットシフト 左から右 operand1 >>> operand2 符号なし右シフト
12 < 関係 左から右 operand1 < operand2 より小さい
12 <= 関係 左から右 operand1 <= operand2 以下
12 > 関係 左から右 operand1 > operand2 より大きい
12 >= 関係 左から右 operand1 >= operand2 以上
12 in 関係 左から右 property in object プロパティがオブジェクトに存在するか確認
12 instanceof 関係 左から右 object instanceof constructor オブジェクトが特定のコンストラクタのインスタンスか確認
11 == 等価 左から右 operand1 == operand2 等価(型変換あり)
11 != 等価 左から右 operand1 != operand2 不等価(型変換あり)
11 === 等価 左から右 operand1 === operand2 厳密等価(型変換なし)
11 !== 等価 左から右 operand1 !== operand2 厳密不等価(型変換なし)
10 & ビット 左から右 operand1 & operand2 ビットAND
9 ^ ビット 左から右 operand1 ^ operand2 ビットXOR
8 | ビット 左から右 operand1 | operand2 ビットXOR
7 && 論理 左から右 operand1 && operand2 論理AND(短絡評価)
6 || 論理 左から右 operand1 || operand2 論理和(短絡評価)
5 ?? 論理 左から右 operand1 ?? operand2 Nullish合体(nullまたはundefinedの場合のみ右辺を評価)
4 ?: 条件 右から左 condition ? expr1 : expr2 条件(三項)演算子
3 = 代入 右から左 variable = value 基本的な代入
3 += 代入 右から左 variable += value 加算代入
3 -= 代入 右から左 variable -= value 減算代入
3 *= 代入 右から左 variable *= value 乗算代入
3 /= 代入 右から左 variable /= value 除算代入
3 %= 代入 右から左 variable %= value 剰余代入
3 <<= 代入 右から左 variable <<= value 左シフト代入
3 >>= 代入 右から左 variable >>= value 右シフト代入
3 >>>= 代入 右から左 variable >>>= value 符号なし右シフト代入
3 &= 代入 右から左 variable &= value ビットAND代入
3 ^= 代入 右から左 variable ^= value ビットXOR代入
3 |= 代入 右から左 variable |= value ビット論理和代入
3 **= 代入 右から左 variable **= value べき乗代入
3 &&= 代入 右から左 variable &&= value 論理AND代入
3 ||=< 代入 右から左 variable ||= value 論理和代入
3 ??= 代入 右から左 variable ??= value Nullish合体代入
2 yield その他 右から左 yield expression ジェネレータ関数の実行を一時停止し、値を返します。
2 yield* その他 右から左 yield* expression 別のジェネレータまたは反復可能オブジェクトに委譲します。
1 , その他 左から右 expr1, expr2, ... 複数の式を順に評価し、最後の式の値を返します。

脚註

編集
  1. ^ ECMA-262::13.8.1 The Addition Operator ( + )
  2. ^ ECMA-262::13.8.2 The Subtraction Operator ( - )
  3. ^ ECMA-262::13.15 Assignment Operators
  4. ^ ECMA-262::13.15.5 Destructuring Assignment
  5. ^ ECMA-262::13.13 Binary Logical Operators
  6. ^ ECMA-262::13.10 Relational Operators
  7. ^ ECMA-262::13.10.2 InstanceofOperator ( V, target )
  8. ^ ECMA-262::13.11 Equality Operators
  9. ^ ECMA-262::13.2.9 The Grouping Operator
  10. ^ ECMA-262::13.3.5 The new Operator
  11. ^ ECMA-262::YieldExpression
  12. ^ ECMA-262::15.5.5 Runtime Semantics: Evaluation
  13. ^ 条件演算子は短絡評価されるので、条件式が真であった場合には第三項は評価されないです。
  14. ^ スプレッド構文は演算子ではないので含めていません。