3.JavaScript演算子

# 算術演算子 

>警告: 記事は機械翻訳があるため、学習メモとして保存、学習参考用のみ

演算子は既存の値から新しい値へのデータ処理の基本的な方法 JavaScriptには様々な演算子があり、主要な演算をすべてカバーしています。

## 概要 

JavaScriptには10個の演算子があり、基本的な演算を行うことができます。

- **加算演算子**:`x + y` 。
- **引き算演算子**:` x-y ` 。
- **乗算子**:`x * y` 。
- **割り算演算子**:`x / y` 。
- **指数演算子**:`x ** y` 。
- **余り演算子**:`x % y` 。
- **自己増加演算子**:`++x`あるいは`x++` 。
- **自己減算子**:`——x`あるいは`x——` 。
数値演算子**:`+x` 。
- **マイナス値演算子**:`-x` 。

引き算、掛け算、割り算の演算法は比較的単純で、それぞれの数学の演算を実行すること 。他にもいくつか算術演算子を紹介しますが、ポイントは加算演算子 。

## 加算子 

### 基本ルール 

足し算(足し算、`+`)は、2つの値の和を求める最も一般的な演算子 。

```javascript 
1 + 1 // 2 
``` 

JavaScriptでは数値以外の加算が可能 。

```javascript 
true + true // 2 
1 + true // 2 
``` 

上のコードでは1行目が2つのブール値の加算で2行目が数値とブール値の加算 どちらの場合も、ブール値は自動的に数値に変換され、加算されます。

特殊なのは、2つの文字列を加算した場合、加算演算子は連結演算子となり、新しい文字列を返して2つの元の文字列を連結します。

```javascript 
'a' + 'bc' // "abc" 
``` 

一方の演算子が文字列で、もう一方の演算子が非文字列の場合、非文字列は文字列に変換され、再び結合されます。

```javascript 
1 + 'a' // "1a" 
false + 'a' // "falsea" 
``` 

加算を実行するか、接続を実行するかは実行時に決定されます。つまり、演算子の違いによって文法が異なることを「オーバーロード(overload)」と呼びます。加算子にはオーバーロードがあり、両方の演算を実行する可能性があるので、注意が必要 。

```javascript 
'3' + 4 + 5 // "345" 
3 + 4 + '5' // "75" 
``` 

上記のコードでは、文字列の位置によって左から右への演算順序が異なります。

加算演算子以外の算術演算子(減算、割り算、乗算など)はオーバーロードしません。すべての演算子を数値に変換し、それに応じた数学的な演算を行うというルール 。

```javascript 
1 - '2' // -1 
1 * '2' // 2 
1 / '2' // 0.5 
``` 

上のコードの減算、割り算、乗算は、文字列を自動的に数値に変換してから演算します。

### オブジェクトの加算 。

演算子がオブジェクトの場合、元の型の値に変換してから加算しなければなりません。

```javascript 
var obj = {p: 1} ;
obj + 2 // "[object object]2" 
``` 

上記のコードで、オブジェクト`obj`を元の型に変換した値は`[object object]`で、これに`2`を加えたもの 。

オブジェクトは元の型の値に変換されます。

まず、自動的にオブジェクトを呼び出す`valueOf`メソッド 。

```javascript 
var obj = {p: 1} ;
obj.valueof () // {p: 1} 
``` 

一般的に、オブジェクトの`valueOf`メソッドは常にオブジェクト自身に戻り、そこで自動的にオブジェクトの`toString`メソッドを呼び出して文字列に変換します。

```javascript 
var obj = {p: 1} ;
obj.valueof ().toString() // "[object object]"
``` 

オブジェクトの`toString`メソッドはデフォルトで`[object object]`を返すので、先ほどの例のような結果になります。

このルールを知っていれば、自分で「valueOf」メソッドや「toString」メソッドを定義して、望む結果を得ることができます。

```javascript 
var obj ={ 
valueOf: function(){ 
return 1 ;
} 
} ;

obj + 2 // 3 
``` 

上のコードでは`obj`オブジェクトを定義する`valueOf`メソッドは`1`を返します`obj + 2`は`3`になりますこの例では、`valueOf`メソッドは元の型の値を直接返すので、`toString`メソッドは呼び出されません。

以下はカスタム「toString」メソッドの例 。

```javascript 
var obj ={ 
toString: function () {
return 'hello' ;
} 
} ;

obj + 2 // "hello2" 
``` 

上のコードでオブジェクト`obj`のtoString`メソッドは文字列`hello`を返します。前述したように、1つの演算子が文字列であれば、加算演算子は接続演算子となり、接続された文字列を返します。

ここで、演算子が「Date」オブジェクトのインスタンスの場合、「toString」メソッドが優先的に実行される特別な例があります。

```javascript 
var obj = new Date() ;
obj.valueof = function () {return 1};
obj.toString = function () {return 'hello'};

obj + 2 // "hello2" 
``` 

上記のコードでは、オブジェクト`obj`は`Date`オブジェクトのインスタンスであり、`valueOf`メソッドと`toString`メソッドをカスタマイズしており、結果として`toString`メソッドが優先的に実行されます。

余り演算子 

余り演算子(`%`)は、前の演算子が後の演算子で割り算された余りを返します。

```javascript 
12 % 5/2 
``` 

なお、演算結果の符号は1つ目の演算子の符号によって決定されます。

```javascript 
- 1% // -1
1 % -2 // 1 
``` 

したがって、負の数の正確な余り値を得るためには、まず絶対値関数を使うことができます。

```javascript 
//間違った書き方 
function isOdd(n) {
  return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false

// ただし
function isOdd(n) {
  return Math.abs(n % 2) === 1;
}
isOdd(-5) // true
isOdd(-4) // false
``` 

剰余演算子は浮動小数点演算にも用いることができます。しかし、浮動小数点数は正確な値ではないため、完全な正確さは得られません。

```javascript 
6.5 % 2.1
// 0.19999999999999973
``` 

## 自己増加と自己減算の演算子 

自己増加と自己減算の演算子は単項演算子で演算子だけが必要 演算子をまず数値に変換し、1を足したり引いたりするの 。元の変数を修正します

```javascript 
var x = 1;
++x // 2
x // 2

--x // 1
x // 1
``` 

上のコードの変数`x`は増加した後、`2`を返して、更に減少して、`1`を返します。どちらの場合も元の変数`x`の値が変わります。

演算後、変数の値が変化する効果を演算の副作用(side effect)といいます。自己増加演算子と自己減算演算子は副作用のある演算子のうち2つだけで他の演算子は変数の値を変えません

自己増加と自己減算の1つの注意点は、変数の後に置くと、変数操作前の値を戻して自己増加/自己減算を行うこと 。変数の前に置いて、まずインクリメント/インクリメントの操作をしてから、変数操作後の値に戻ります。

```javascript 
var x = 1 ;
var y = 1 ;

x++ // 1 
++y // 2 
``` 

上のコードの中で、`x`は先に現在の値を返して、それから自己増加しますので、`1`を得ます;`y`は増加して新しい値を返すので`2`が得られます

## 数値演算子,負の数値演算子 

数値演算子(`+`)も加算を使いますが、単項演算子(オペランドは1つ)で、加算演算子は2項演算子(オペランドは2つ) 。

数値演算子は、任意の値を数値に変換できるように働きます(Number関数と同じように働きます)。

```javascript 
+true // 1 
+[] // 0 。
+{} // NaN 
``` 

上のコードは、非数値が数値演算子を経て数値になっていることを示しています(最後の行`NaN`も数値)。具体的な型変換のルールについては、「データ型変換」の章を参照されたいと思います。

負の値演算子(`-`)は、同じように1つの値を数値に変換する機能を持っていますが、正負の値が得られます。2つの負の値の演算子を連用して、数値の演算子に等しい 。

```javascript 
var x = 1 ;
-x // -1 
-(-x) // 1 
``` 

上のコードの最後の行の括弧が必要 そうでないと自己減算子になってしまいます

数値記号と負の数値記号は元の変数の値を変えることなく新しい値を返します

指数演算子 

指数演算子(`**`)は指数演算を行います。前の演算子が底で、次の演算子が指数 。

```javascript 
2 ** 4 // 16 
``` 

指数演算子は左結合ではなく右結合 つまり、複数の指数演算子を連用する場合は、一番右端の計算を先に行います。

```javascript 
//2 **(3 ** 2)に相当
2 ** 3 ** 2
// 512 
``` 

上記のコードでは、指数演算子は右結合なので、1つ目ではなく2つ目の指数演算子を先に計算します。

## 代入演算子 

代入演算子(Assignment Operators)は、変数に値を与えます。

最も一般的な代値演算子は、もちろん等号(`=`) 。

```javascript 
//1を変数xに割り当てます。
var x = 1 ;

//変数yの値を変数xに割り当てます。
var x = y ;
``` 

代入演算子は他の演算子と組み合わせてバリエーションを作ることもできます。以下は算術演算子との組み合わせ 。

```javascript 
//はx = x + yに等しい 。
x += y 

//はx = x-yに等しい 。
x = y 

//はx = x * yに等しい 
x *= y 

//はx = x / yに等しい 。
x /= y 

// x = x % yに相当します。
x %= y 

// x = x ** yに等しい 。
x **= y 
``` 

以下はビット演算子との組み合わせ (ビット演算子については後述)。

```javascript 
// x = x >> yに等しい 。
x >>= y 

// x = x << yに相当します。
x <<= y 

// x = x >>> yに等しい 。
x >>>= y 

// x = x & yに等しい 。
x &= y 

/ /イコールx = x | y
x | = y

// x = x ^ yに等しい 。
x ^= y 
``` 

これらの複合的な付値演算子は、まず指定された演算を行い、左の変数に値を返します。
# 比較演算子 

## 概要 

比較演算子は2つの値の大きさを比較し、指定された条件が満たされているかどうかを示すブール値を返します。

```javascript 
2 > 1 // true 
``` 

上のコードは`2`が`1`より大きいかどうかを比較して、`true`を返します。

>なお、比較演算子は数値だけでなく様々な種類の値を比較することができます。

JavaScriptには8つの比較演算子があります。

- `>`演算子より大きい 
- `<`は演算子より小さい 。
- `<=`は演算子以下 。
- `>=`演算子以上 
- `==`等価演算子 
- `===`厳密に等しい演算子 。
ー !=`不等価演算子 
ー !==`厳密な不等価演算子 。

8つの比較演算子は2種類に分けられます等価比較とそうでない比較 規則は違います。非等価比較の場合、アルゴリズムは2つの演算子が両方とも文字列かどうかを見て、そうであれば辞書順に比較します(実際にはUnicodeの符号点を比較します)。そうでなければ、両方の演算子を数値に変換し、その数値の大きさを比較します。

## 非等価演算子:文字列の比較 

文字列は辞書順に比較されます。

```javascript 
'cat' > 'dog' // false 
'cat' > 'catalog' // false 
``` 

JavaScriptエンジン内部では、最初に頭文字のUnicodeコードポイントを比較します。等しい場合は2番目の文字のUnicode符号点を比較します。

```javascript 
'cat' > 'cat' // true' 
``` 

上のコードでは、小文字の`c`のUnicode点(`99`)が大文字の`c`のUnicode点(`67`)より大きいため、`true`が返されます。

すべての文字にUnicodeの符号点があるため、漢字の比較も可能 。

```javascript 
'大' > '小' // false
``` 

上のコードでは、"大"のUnicodeの符号点は22823で、"小"は23567なので`false`を返します。

## 非等価演算子:非文字列の比較 

2つの演算子のうち少なくとも1つが文字列でない場合は、次の2つに分ける必要があります。

**(1)元の型値** 。

両方の演算子が元の型の値の場合は、数値に変換してから比較します。

```javascript 
5 > '4' // true 
// 5 > Number('4')に相当します。
//つまり5 > 4 

true > false // true 
//はNumber(true) > Number(false)に相当します。
//つまり1 > 0 

2 > true // true 
// 2 > Number(true)に相当します。
//つまり2 > 1 
``` 

上のコードでは、文字列とブール値はいずれも数値に変換してから比較します。

ここで注意が必要なのは`NaN`との比較 。' NaN '自身を含む任意の値と' NaN 'が等しくない演算子を使って比較すると' false 'が返ってきます。

```javascript 
1 > NaN // false 
1 <= NaN // false 
'1' > NaN // false 
'1' <= NaN // false
< NaN > NaN // false 
<= NaN // false >
``` 

**(2)対象** 

演算子が対象の場合は、元の型の値に変換して比較します。

オブジェクトは元の型の値に変換され、アルゴリズムはまず`valueOf`メソッドを呼び出します。オブジェクトが戻ってきた場合は、「toString」メソッドを呼び出します。詳しくは「データタイプの変換」の章を参照してください。

```javascript 
var x =[2] ;
x > '11' // true 
//[2].valueOf().toString() > '11'に相当します。
//即'2' > '11' 

x. valueof = function () {return '1'};
x > '11' // false 
//は(function () {return '1'})() > '11'に相当します。
//即'1' > '11' 
``` 

2つの対象の比較も同じ 。

```javascript 
[2] > [1] // true 。
//どもっ[2]. valueof () . tostring () > [1] . valueof () . tostring ()
//即'2' > '1' 

[2] > [11] // true 。
//どもっ[2]. valueof () . tostring () > [11] . valueof () . tostring ()
//即'2' > '11' 

({x: 2}) >= ({x: 1}) // true 
//どもった(2}){x: . valueof () . tostring () > = ({x: 1}) . valueof () . tostring ()
//即'[object object]' >= '[object object]' 
``` 

厳密な等価演算子 

JavaScriptには2種類の等価演算子があります:`==`と`===` 。

簡単に言えば、等価演算子(`==`)は2つの値が等しいかどうかを比較し、厳密な等価演算子(`===`)は「同じ値」かどうかを比較します。2つの値が同じ型でない場合、厳密な等価演算子(`===`)は直接`false`を返し、等価演算子(`==`)はそれらを同じ型に変換し、厳密な等価演算子で比較します。

ここでは厳密な等価演算子のアルゴリズムを紹介します。

**(1)異なる種類の値 **

2つの値の型が異なる場合は、直接`false`を返します。

```javascript 
1 === "1" // false 
"true" // false 
``` 

上記のコードでは、数値の`1`と文字列の" 1 "、ブール値の`true`と文字列の"true"`を比較していますが、型が異なるため、同じ`false`となります。

**(2)同じクラスの元の型値** 。

同じ型の元の型の値(数値、文字列、ブール値)を比較した場合、同じ値なら`true`、違う値なら`false`を返します。

```javascript 
1 === 0x1 // true 
``` 

上のコードは十進法の`1`と十六進法の`1`を比較します。型も値も同じなので`true`を返します。

`NaN`は(それ自身を含めて)どの値とも等しくありません。また、正`0`は負`0` 。

```javascript 
NaN === NaN // false
+0 === -0 // true 
``` 

**(3)複合型値** 。

2つの複合型(オブジェクト、配列、関数)のデータを比較するとき、それらの値が等しいかどうかではなく、同じアドレスを指しているかどうかを比較します。

```javascript 
{} === {} // false 
[] === [] // false 
(function () {} === function () {}) // false
``` 

上のコードはそれぞれ2つのヌルオブジェクト、2つのヌル配列、2つのヌル関数を比較して、結果はすべて等しくありません。なぜなら、復合型の値については、厳密に等しい演算は同じメモリアドレスを参照しているかどうかを比較し、演算子の両方の空のオブジェクト、空の配列、空の関数の値は、すべて異なるメモリアドレスに格納され、結果は当然`false` 。

2つの変数が同じオブジェクトを参照している場合、それらは等しい 。

```javascript 
var v1 ={} ;
var v2 = v1 ;
v1 === v2 // true 。
``` 

なお、2つのオブジェクトの比較では、厳密に等しい演算子はアドレスを、それ以上の演算子は値を比較します。

```javascript 
var obj1 ={} ;
var obj2 ={} ;

obj1 > obj2 // false 
obj1 < obj2 // false > 。
obj1 === obj2 // false 
``` 

上の3つの比較のうち、最初の2つは値、最後の1つはアドレスを比較していますので、いずれも`false`を返します。

** (4) undefinedとnull** 

' undefined 'と' null 'は自分自身と厳密に等しい 。

```javascript 
undefined === undefined // true
null == null // true 
``` 

宣言された変数のデフォルト値は' undefined 'なので、宣言されていない2つの変数は等しいことになります。

```javascript 
var v1 ;
var v2 ;
v1 === v2 // true 。
``` 

## 厳密な不等価演算子 

厳密な等価演算子には「厳密な不等価演算子」(`!==`)、そのアルゴリズムは厳密な等価演算子の結果を求めてから、逆の値を返します。

```javascript 
1 !== '1' // true 
//に等しい 
 !(1 === '1' )
``` 

上のコードは感嘆符` !`は後の式の逆の値を求めるもの 。

等価演算子 

等価演算子は同じ種類のデータを比較するのに使われ、厳密な等価演算子と全く同じ 。

```javascript 
1 == 1.0 
//に等しい 
1 === 1.0 
``` 

異なる種類のデータを比較するとき、等価演算子はデータを型変換してから厳密な等価演算子で比較します。以下、いくつかのケースに分けて、異なる種類の値を比較するためのルールを検討します。

**(1)元の型値** 。

元の型の値は数値に変換して比較します。

```javascript 
1 == true // true 
//1 === Number(true)に相当します。

0 == false // true 
//0 === Number(false)に相当します。

2 == true // false 
//2 === Number(true)に相当します。

2 == false // false 
//2 === Number(false)に相当します。

'true' == true // false 
//Number('true') === Number(true)に相当します。
//NaN === 1に相当します。

'' == 0 // true 
//はNumber('') === 0に等しい 。
0 === 0に等しい 

'' == false // true 
//Number('') === Number(false)に相当します。
//0 === 0に等しい 

'1' == true // true 
//はNumber('1') === Number(true)と同じ 。
//1 === 1に等しい 

'\n 123 \t' == 123 // true 
//というのは、文字列が数字になるときに、前・後のフレームが省略されるから 。
``` 

上のコードは文字列とブール値の両方を数値化して比較します具体的な文字列やブール値の型変換規則については、「データ型変換」の章を参照されたいと思います。

**(2)オブジェクトを元の型値と比較します**

オブジェクト(ここでは配列や関数を含む広義のオブジェクトを指す)が元の型の値と比較された場合、オブジェクトは元の型の値に変換され、さらに比較されます。

具体的には、先にオブジェクトの`valueOf()`メソッドを呼び出して、元の型の値を得たら、前のセクションの規則に従って、お互いを比較します。それでもオブジェクトが出てきたら、再び`toString()`メソッドを呼び出して文字列形式を得て、比較します。

元の型値と配列を比較した例を以下に示します。

```javascript 
//配列と数値の比較 。
[1] == 1 // true 

//配列と文字列の比較 
[1] == '1' // true 
[1, 2] == '1,2' // true 

//オブジェクトとブール値の比較 
[1] == true 。
[2] == true // false 。
``` 

先の例では、JavaScriptエンジンは先に配列`[1]`に対して配列の`valueOf()`メソッドを呼び出し、返ってくるのはやはり配列なので、次に配列の`toString()`メソッドを呼び出し、文字列形式を得て、前のセクションのルールに従って比較します。

以下はもっと直接的な例 。
```javascript 
const obj ={ 
valueOf: function(){ 
console.log('実行valueOf()');
return obj ;
} ,
toString: function () {
console.log('実行toString()');
return 'foo' ;
} 
} ;

obj == 'foo' 
//実行valueOf() 。
// 実行toString()
// true 
``` 

上記の例では、`obj`は`valueOf()`と`toString()`のメソッドをカスタマイズしたオブジェクト 。このオブジェクトを文字列`'foo'`と比較すると、`valueOf()`と`toString()`メソッドが次々に呼び出され、最後に`'foo'`が返されるので、比較結果は`true`となります。

** (3) undefinedとnull** 

「undefined」と「null」は、自分自身と比較したり、お互いを比較したりした場合にのみ、「true」を返します。他の種類の値と比較すると「false」となります。

```javascript 
undefined = undefined // true 
null == null // true 
undefined == null // true 

false == null // false 
false == undefined 

0 == null // false 
0 == undefined // false 
``` 

**(4)等価演算子の欠点** 。

等価演算子の暗黙の型変換は、直観に反する結果をもたらします。

```javascript 
0 == '' // true 
0 == '0' // true 

2 == true // false 
2 == false // false 

false == 'false' // false 
false == '0' // true 

false == undefined 
false == null // false 
null == undefined // true 

' \t\r\n ' == 0 // true 
``` 

これらの式は直感とは異なり、間違いやすいもの 。したがって、等価演算子(`==`)を使用せず、厳密な等価演算子(`===`)のみを使用することをお勧めします。

## 不等価演算子 

等価演算子には対応する「不等価演算子」(`!=`)で、そのアルゴリズムはまず等しい演算子の結果を求めて、それから反対の値を返します。

```javascript 
1 != '1' // false 

//に等しい 
 !(1 == '1' )
``` 

# ブール演算子 

## 概要 

ブール演算子は式をブール値に変換するのに使われ、4つの演算子からなります。

-は逆演算子を取ります:`!` 
-かつ演算子:`&&` 
-や演算:` | | `
-三元演算子:` か?「 」

## 逆演算子を取ります(!)

逆演算子はブールの値を逆にするための感嘆符 つまり`true`は`false`に、`false`は`true`になります

```javascript 
 !true // false 
 !false // true 
``` 

非ブール値の場合、逆演算子を取るとブール値に変換されます。次の六つの値を逆算して「true」、それ以外の値は「false」と覚えておくといいでしょう。

- ' undefined ' 
- `null 
- `false 
- 0 
- `NaN 
空文字列(`''`) 

```javascript 
 !undefined // true
!null // true
!0 // true
!NaN // true
!"" // true

!54 // false
!'hello' // false
![] // false
!{} // false
``` 

上のコードでは、どのような種類の値であっても、取逆演算をするとブール値になります。

1つの値を2回連続して逆演算すると、対応するブール値に変換することになり、ブーラン関数と同じ働きをします。これはタイプ変換でよく使われる書き方 。

```javascript 
!!x
// 等
Boolean(x)
``` 

上のコードでは、`x`がどのような種類の値であっても、2回の逆演算を経て、`Boolean`関数の結果と同じブール値になります。したがって、2回逆にするというのは、ある値をブール値に変換するという簡単な書き方 。

## かつ演算子(&&) 。

演算子(`&&`)は多くの式の値を求めます。

1つ目の演算子のブール値が' true 'なら2つ目の演算子の値を返します(ブール値ではなく値 ので注意)。1つ目の演算子のブール値がfalseであれば、1つ目の演算子の値を返し、2つ目の演算子の値は求めません。

```javascript 
't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""

var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1
``` 

上記のコードの最後の例では、1つ目の演算子のブール値が`false`である場合は、2つ目の演算子の値を求めずにその値`0`を返すので、変数`x`の値は変わりません。

この2つ目の演算子を飛ばしてしまう仕組みを「ショート」と呼びます。プログラマの中には`if`構造の代わりにそれを使う人もいます。例えば、次のような`if`構造のコードを使って書き換えることができます。

```javascript 
if (i) {
  doSomething();
}

// 等

i && doSomething();
``` 

上記の2つの表記は等価 が、後者は目的が見えにくく、除却もしにくいので、慎重に使うことをお勧めします。

この場合、1つ目のブール値が`false`である式の値を返します。すべての式のブール値が`true`の場合は、最後の式の値を返します。

```javascript 
true && 'foo' && '' && 4 && 'foo' && true
// ''

1 && 2 && 3
// 3
``` 

例1では最初のブール値が`false`の式は3番目の式なので空の文字列になります例2では全ての式のブール値は`true`なので最後の式の値`3`を返します

## 或演算(|)|

或演算(` | | `)も余りエクスプレション用の求値。1つ目の演算子のブール値がtrueの場合、1つ目の演算子の値を返し、2つ目の演算子の値を求めません。1つ目の演算子のブール値が`false`であれば、2つ目の演算子の値を返します。

```javascript 
't' || '' // "t"
't' || 'f' // "t"
'' || 'f' // "f"
'' || '' // ""
``` 

短絡規則はこの演算子にも適用されます。

```javascript 
var x = 1;
true || (x = 2) // true
x // 1
``` 

上のコードでは、1つ目の演算子は`true`なので、2つ目の演算子はもう実行しません。よって、`x`の値は変わりません。このように、1つ目の式の値だけで2つ目の式を実行するかどうかを制御する仕組みを「ショート」と呼びます。

または演算子は複数連用できます。この場合、最初のブール値が`true`の式の値を返します。全ての式が`false`の場合は最後の式の値を返します

```javascript 
false || 0 || '' || 4 || 'foo' || true
// 4

false || 0 || ''
// ''
``` 

上記のコードの例では、最初のブール値が`true`の式は4番目の式なので、数値4が得られます。例2では、すべての式のブール値は`false`なので、最後の式の値を返します。

変数のデフォルト値を設定するときによく使われます

```javascript 
function saveText(text) {
  text = text || '';
  // ...
}

// 或
saveText(this.text || '')
``` 

上記のコードは、引数が関数呼び出し時に提供されていない場合、引数がデフォルトで空文字列に設定されていることを示しています。

## 三項条件演算子?: 

三項条件演算子は疑問符(?) 。コロン(:)で3つの式を区切りますJavaScript言語で3つの演算子を必要とする唯一の演算子 。1つ目の式のブール値が`true`の場合は2つ目の式を返しますそうでない場合は3つ目の式を返します

```javascript 
't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"
``` 

上のコードの`t`と`0`のブール値はそれぞれ`true`と`false`なので、それぞれ2番目と3番目の式の値を返します。

通常、三項条件式は`if…else`文にも同様の効果があり、前者でも表現できるものは後者でも表現できます。しかし両者には大きな違いがあります`if…else`は文であり、値を返しません。三項条件式は、戻り値を持つ式 。よって、値を返す必要がある場合は、3つの条件式しか使えず、`if..は使えません。else` 。

```javascript 
console.log(true ? 'T' : 'F');
``` 

上記のコードでは、`console.log`メソッドのパラメータは1つの式でなければなりません。この場合、3つの条件式しか使えません。もし使います`if…else`文はコードの書き方を変えなければなりません

# バイナリビット演算子

## 概要

バイナリビット演算子は、バイナリビットを直接計算するために使用され、全部で7つあります。

- バイナリまたは演算子 (or): 記号は '|' で、両方のバイナリ ビットが '0' の場合、結果は '0' になり、それ以外の場合は '1' になります。
- 二項 & 演算子 (and): 記号 '&' は、両方の 2 進ビットが 1 の場合、結果は 1 になり、それ以外の場合は 0 であることを意味します。
- 二項演算子なし(not):記号は「~」で、2進ビットの否定を示します。
- XOR演算子:記号「^」は、2つのバイナリビットが同じでない場合、結果は1になり、そうでない場合は0になることを意味します。
- 左シフト:以下で説明するように、記号は「<<」 。 - 右シフト:以下で説明するように、記号は「>>」 。
- ゼロで塗りつぶされた右シフト:以下で説明するように、記号は「>>>」 。

これらのビット演算子は各ビットを直接処理するため、非常に低レベルの操作であり、利点は非常に高速であり、欠点は非常に直感的でないことであり、多くの場合、コードの理解とトラブルシューティングが困難になります。

ビット演算子は整数でのみ機能し、演算子が整数でない場合は、実行前に自動的に整数に変換されることに注意することが重要 。 また、JavaScript では値は 64 ビット浮動小数点数として格納されますが、ビット演算は 32 ビット符号付き整数として実行され、戻り値も 32 ビット符号付き整数 。

``` javascript
i = i | 0;
``` 

上記のコード行の意味は、「i」(整数または10進数)を32ビット整数に変換すること 。

この機能を使用すると、任意の値を 32 ビット整数に変換する関数を記述できます。

``` javascript
function toInt32(x) {
  return x | 0;
}
``` 

上記の関数は「0」または算術値を持つ任意の値を取り、このビット演算は値を32ビット整数に自動的に変換します。 この機能の使用方法は次のとおり 。

``` javascript
toInt32(1.001) // 1
toInt32(1.999) // 1
toInt32(1) // 1
toInt32(-1) // -1
toInt32(Math.pow(2, 32) + 1) // 1
toInt32(Math.pow(2, 32) - 1) // -1
``` 

上記のコードでは、「toInt32」は小数を整数に変換できます。 通常の整数の場合、戻り値に変更はありません。 2 の 32 乗以上の整数の場合、32 桁を超える桁は丸められます。

## 二項演算子

二項演算子 ('|') は 2 つの演算子をビット単位で比較し、2 つの 2 進数ビットのうち 1 つだけが '1' であれば '1' を返し、そうでなければ '0' を返します。

``` javascript
0 | 3 // 3
```

上記のコードでは、「0」と「3」のバイナリ形式はそれぞれ「00」と「11」であるため、バイナリまたは算術演算を行うと「11」(つまり「3」)になります。

ビット演算は整数に対してのみ有効であり、小数点が検出されると、小数部分が四捨五入され、整数部分のみが保持されます。 したがって、2進数または算術の小数点が「0」の場合、数値の小数部分を削除すること、つまり桁全体を取ることと同等 。

``` javascript
2.9 | 0 // 2
-2.9 | 0 // -2
```

この丸め方法は、32ビット整数「2147483647」の最大値を超える数値には適用されないことに注意してください。

``` javascript
2147483649.4 | 0;
// -2147483647
```

## 二項演算子 &

二項演算子 ('&') のルールは、2 つの演算子をビットごとに比較することであり、2 つのバイナリ ビットの 1 つが '0' である限り、'0' を返し、それ以外の場合は '1' を返します。

``` javascript
0 & 3 // 0
```

上記のコードでは、0 (バイナリ '00') と 3 (バイナリ '11') のバイナリと算術演算の結果は '00' (つまり '0') になります。

## 二項 no 演算子

二項 no 演算子 ('~') は、各 2 進数ビットを逆の値に変更します ('0' は '1' になり、'1' は '0' になります)。 結果は、コンピュータ内部の数値表現メカニズムのために理解しにくい場合があります。

``` javascript
~ 3 // -4
```

上記の式は、'3'に対してバイナリの負の演算を行い、'-4'を与えます。 これは、JavaScript が内部 べての演算子を 32 ビットの 2 進整数に変換してから操作を実行するため 。

32 ビット整数形式の '3' は '00000000000000000000000000000011' で、2 進数の負の演算の結果は '11111111111111111111111111111100' になります。 最初のビット (符号ビット) は 1 であるため、この数値は負の数 。 JavaScript は内部的に補数の形式を使用して負の数を表します、つまり、この数値から 1 を減算し、もう一度逆を取り、負の符号を追加して負の数に対応する 10 進値を取得する必要があります。 この数値から 1 を引くと「11111111111111111111111111111011」になり、もう一度取ると「00000000000000000000000000000100」になり、さらにマイナス記号は「-4」になります。 このようなプロセスがより面倒であることを考えると、-1に等しい逆値に数値が加算されることを単純に覚えておくことができます。

``` javascript
~ -3 // 2
``` 

上記の式は次のように計算でき、「-3」の逆数は「-1」から「-3」を引いた値に等しく、結果は「2」になります。

整数に対して 2 回連続で 2 回連続して 2 項の演算を行い、それ自体を取得します。

``` javascript
~~3 // 3
```

すべてのビット演算は、整数に対してのみ有効 。 2 進数の負の演算で 10 進数が検出されると、小数部分も四捨五入され、整数部分のみが保持されます。 したがって、10 進数に対する 2 つの連続した 2 進数の no 演算は、丸めの効果を得ることができます。

``` javascript
~~2.9 // 2
~~47.11 // 47
~~1.9999 // 1
~~3 // 3
```

算術演算を使用しない 2 進数を使用した丸めは、すべての丸め方法の中で最も高速 。

文字列に対してバイナリ no 操作を実行するために、JavaScript エンジンは最初に 'Number' 関数を呼び出して文字列を数値に変換します。

``` javascript
~// 相当 ~Number('011')
~'011'  // -12

// 相当~Number('42 cats')
~'42 cats' // -1

// 相当~Number('0xcafebabe')
~'0xcafebabe' // 889275713

// 相当~Number('deadbeef')
~'deadbeef' // -1
```

「Number」関数で文字列を数値に変換するためのルールについては、「データの型変換」の章を参照してください。

他のタイプの値の場合、二項の no 演算も最初に 'Number' の数値に変換されてから処理されます。

``` javascript
~Number([]) と等価
~[] // -1

~Number(NaN) と同等
~NaN // -1

~Number(null) と同等
~null // -1
```

## XOR演算子

XOR 演算 ('^') は、2 つの 2 進ビットが同じでない場合は '1' を返し、2 つの 2 進ビットが同じ場合は '0' を返します。

``` javascript
0 ^ 3 // 3
```

上記の式では、'0'(バイナリ'00')と'3'(バイナリ'11')はXORであり、それぞれのバイナリビットが異なるため、'11'(つまり'3')が得られます。

「XOR演算」には特別なアプリケーションがあり、2つの数値「a」と「b」を連続して3つのXOR演算「a^=b; b^=a; a^=b; 'は、それらの値を[交換](http://en.wikipedia.org/wiki/XOR_swap_algorithm)できます。 つまり、XOR演算を使用して、一時変数を導入せずに2つの変数の値を入れ替えることができます。

``` javascript
var a = 10;
var b = 99;

a ^= b, b ^= a, a ^= b;

a // 99
b // 10
```

これは、2 つの変数の値を入れ替える最速の方法 。

XOR 演算は、切り上げにも使用できます。

``` javascript
12.9 ^ 0 // 12
```

## Shift-Left 演算子

左シフト演算子 ('<<') は、数値のバイナリ値を '0' で終わる指定された桁数だけ左にシフトする、つまり '2' を指定された累乗に乗算することを意味します。 左に移動すると、最上位の符号ビットが一緒に移動します。

``` javascript
//4 の 2 進数は 100  。
//左に 1 つシフトすると 1000 (つまり、10 進数で 8) になります。
//2 の 1 乗に相当
4 << 1
// 8

-4 << 1
// -8
```

上記のコードでは、'-4' の 2 進数形式が '11111111111111111111111111111100' であるため、'-4' を 1 つ左にシフトして '-8' を取得し、数値を左にシフトして '11111111111111111111111111111000' を取得し、10 進数に変換され (1 で減算して否定し、負の符号を加えて) '-8' になります。

左に 0 ビットシフトすると、値を 32 ビット整数に変換することと同等であり、丸めと同等であり、正の数と負の数の両方に有効 。

```javascript
13.5 << 0
// 13

-13.5 << 0
// -13
```

シフトレフト演算子は、バイナリ値に非常に便利 。

```javascript
var color = {r: 186, g: 218, b: 85};

// RGB to HEX
// (1 << 24)の作用は　结果が6桁数を保証する
var rgb2hex = function(r, g, b) {
  return '#' + ((1 << 24) + (r << 16) + (g << 8) + b)
    .toString(16) // １６進制に変更、そしてstringに変更
    .substr(1);   // 
}

rgb2hex(color.r, color.g, color.b)
// "#bada55"
```

上記のコードでは、シフトレフト演算子を使用して、色のRGB値をHEX値に変換しています。

## 右シフト演算子

右シフト演算子 ('>>') は、数値の 2 進値を右にシフトする桁数を示します。 正の数の場合、すべての表は「0」で埋められます。 ネガティブな場合は、頭に「1」を作ります。 右シフト演算子は、基本的には、指定された累乗の '2' で除算することと同等  (最上位ビットである符号ビットが移動に関与します)。

```javascript
4 >> 1
// 2
/*
4 の 2 進数形式は 00000000000000000000000000000100 なので、
右に1つ移動すると00000000000000000000000000000010、
これは小数点以下の 2  
*/

-4 >> 1
// -2
/*
-4 の 2 進数形式は 11111111111111111111111111111100 であるため、
右に1つ移動し、頭を1つにして、11111111111111111111111111111110を取得し、
これは 10 進数で -2  
*/
```

右シフト操作は、2 の分割可能性をシミュレートします。

```javascript
5 >> 1
// 2
//5 / 2 = 2 に相当します。

2>>21日
// 5
//21 / 4 = 5 に相当します。

3>>21日
// 2
//21 / 8 = 2 に相当します。

4>>21日
// 1
//21 / 16 = 1 に相当します。
```

## ヘッドゼロの右シフト演算子

右シフト演算子 ('>>>') と右シフト演算子 ('>>') の違いは 1 つだけで、数値の 2 進形式を右にシフトすると、符号ビットに関係なくヘッドがゼロになること 。 したがって、操作は常に正の値を取得します。 正の数の場合、この操作の結果は右シフト演算子 ('>>') の結果とまったく同じ が、主な違いは負の数にあります。

```javascript
4 >>> 1
// 2

-4 >>> 1
// 2147483646
/*
-4 の 2 進数形式は 11111111111111111111111111111100 であるため、
符号付きビットを 1 ビット右にシフトして01111111111111111111111111111110を取得します。
これは小数点以下の2147483646 。
*/
```

この操作は、実際には値を 32 ビット符号なし整数に変換します。

負の整数がコンピューター内にどのように格納されているかを確認する最も速い方法は、この演算子を使用すること 。

```javascript
-1 >>> 0 // 4294967295
```

上記のコードは、'-1' が 32 ビット整数として使用される場合、内部ストレージ形式は符号なし整数形式で解釈され、値が 4294967295 (つまり、'(2^32)-1'、つまり '11111111111111111111111111111111' に等しい) であることを示しています。

スイッチのスイッチ 

ビット演算子はオブジェクトの属性を設定するスイッチとして使うことができます。

あるオブジェクトに4つのスイッチがあり、それぞれが1つの変数だとします。では、4桁の2進数を設定し、それぞれのビットにスイッチを入れます。

```javascript 
var FLAG_A = 1 ;// 0001 
var FLAG_B = 2 ;// 0010 
var FLAG_C = 4 ;// 0100 
var FLAG_D = 8 ;// 1000 
``` 

上のコードはA、B、C、Dの4つのスイッチを設定し、それぞれがバイナリビットを占有しています。

すると、バイナリと演算を使って、現在の設定で指定のスイッチが入っているかどうかをチェックすることができます。

```javascript 
var flags = 5 ;//バイナリの0101 。

if (flags & FLAG_C){ 
//… 
} 
// 0101 & 0100 => 0100 => true 
``` 

上のコードはスイッチ`C`がオンになったかどうかを検査します。開いていれば「true」、そうでなければ「false」と返されます。

ここで、「A」、「B」、「D」の3つのスイッチをオンにすると仮定して、マスク変数を作ることができます。

```javascript 
var mask = FLAG_A | FLAG_B | FLAG_D;
// 0001 | 0010 | 1000 => 1011
``` 

上のコードは`A`、`B`、`D`の3つの変数に対して2進数あるいは演算を行って、マスク値が2進数の`1011`を得ます。

マスクのおかげで、バイナリや演算によって指定されたスイッチが確実にオンになります。

```javascript 
flags = flags | mask;
``` 

上のコードで計算された変数「flags」は3つのスイッチのバイナリビットがオンになっています

バイナリと演算は、スイッチの設定と異なるすべての現在の設定をオフにすることができます。

```javascript 
flags = flags & mask ;
``` 

排他的論理和演算は現在の設定を切り替えることができます。つまり、最初に実行すると現在の設定とは逆の値になり、もう一度実行すると元の値になります。

```javascript 
flags = flags ^ mask;
``` 

2進数の否定的な演算は現在の設定を反転することができて、すなわち元は`0`に設定して、演算後`1`になります;元は`1`に設定して、演算後に`0`になります。

```javascript 
flags = ~flags ;
``` 

##リンク参照 

- Michal Budzynski氏[JavaScript:the inincreasingnumbers known parts . bitwise operators] (https://michalbe.blogspot.com/2013/03/javascript-less-known-parts-bitwise.html)
−アクセルrauschmayer、[ベーシックjavascript for the impatient programmer] (http://www.2ality.com/2013/06/basic-javascript.html)
Mozilla Developer Network [bitwise operators] (https://developer.mozilla.org/en-us/docs/web/javascript/reference/operators/bitwise_operators)

# その他の演算子,演算順序 

## void演算子 

' void '演算子は式を実行して何の値も返さずに' undefined 'を返します

```javascript 
void 0 // undefined 
void(0) // undefined 
``` 

上は`void`演算子の二種類の書き方で、どちらも正しい 。後者の、いつもカギ括弧を使うことをおすすめします。`void`演算子は優先度が高いので、括弧を使わないと間違った結果になりやすい 。例えば、`void 4 + 7`は、実際には`(void 4) + 7`と同じ 。

以下は`void`演算子の一例 。

```javascript 
var x = 3 ;
void (x = 5) //undefined 
x // 5 
``` 

この演算子の主な用途は、ブラウザのブックマークレットや、ハイパーリンクにコードを挿入してページのジャンプを防ぐこと 。

下記のコードをご覧いただきます。

```html 
<script>
function f() {
  console.log('Hello World');
}
</script>
<a href="http://example.com" onclick="f(); return false;"> click </a>
``` 

上記のコードでは、リンクをクリックすると「onclick」のコードが先に実行されます。onclickは「false」を返しますので、example.comに遷移することはありません。

`void`演算子は上記の代わりに書くことができます。

```html 
<a href="javascript: void(f())">文字</a>
``` 

以下はより現実的な例で、ユーザーがリンクをクリックしてフォームを提出しても、ページ遷移が発生しません。

```html 
<a href="javascript: void(document.form.submit())">
提出します
</a> 。
``` 

コンマ演算子 

コンマ演算子は2つの式の値を求め、後者の式の値を返します。

```javascript 
'a', 'b' // "b" 

var x = 0 ;
var y = (x++, 10) ;
x // 1 
y // 10 
``` 

上のコードではコンマ演算子は次の式の値を返します

コンマ演算子の1つの用途は、ある値を返す前に補助的な操作を行うこと 。

```javascript 
var value = (console.log('Hi!'), true );
//ハイ !

value // true 
``` 

上のコードでは、コンマの前の動作を先に実行し、コンマの後の値を返します。

## 演算手順 。

### 優先度 

JavaScriptでは、各種演算子の優先度(Operator Precedence)が異なります。優先度の高い演算子が先に実行され、優先度の低い演算子が後に実行されます。

```javascript 
4 + 5 * 6 // 34 
``` 

上のコードでは乗算子(`*`)の方が加算子(`+`)より優先度が高いので、乗算を先に実行して加算を実行すると次のようになります。

```javascript 
4 +(5 * 6) // 34 。
``` 

複数の演算子が混在していると、戸惑うようなコードになってしまうことがあります。

```javascript 
var x = 1;
var arr = [];

var y = arr.length <= 0 || arr[0] === undefined ? x : arr[0];
``` 

上のコードでは変数`y`の値がわかりにくいの が、この式には5つの演算子が含まれているので、誰が一番優先度が高いのか、なかなか覚えられません。

言語規格によって、この五演算の優先順位が高いから低い順:以下(` < = `)、厳格だ相(` = = = `)や(` | | `)、三元(` ?:`)、イコール(`=`) 。したがって、上の式では、実際の手順は次のようになります。

```javascript 
var y = ((arr.length <= 0) || (arr[0] === undefined)) ? x : arr[0];
``` 

すべての演算子の優先度を覚えるのは、とても難しく、必要もありません。

### 括弧の役割 

括弧(`()`)は最も優先度が高く、括弧内の式が1番目の演算を行うので、演算の優先度を上げることができます。

```javascript 
(4 + 5) * 6 // 54 。
``` 

上のコードでは、括弧を使っているので、加算が乗算より先に実行されます。

演算子の優先度は非常に複雑で厳格に規定されているため、常に括弧を使うことをお勧めします。

ちなみに括弧は演算子ではなく構文構造 2つの使い方があります。一つは式を括弧の中に入れて優先度を上げる方法。もう1つは関数の後に続き関数を呼び出すこと 

なお、括弧は演算子ではありませんので、演算の優先度のみを変更する求値作用はありません。

```javascript 
var x = 1;
(x) = 2;
``` 

上のコードの2行目は、括弧に求値作用があれば`1 = 2`となりますが、これはエラー 。しかし、上のコードは実行でき、括弧は優先度を変更するだけで、値は求めません。

つまり、式全体が丸括弧の中に入っていては、何の効果もありません。

```javascript 
(expression )
//に等しい 
expression 
``` 

関数は括弧の中に入れられ、関数自身に戻ります。括弧が関数の後に続く場合は、関数を呼び出していることを意味します。

```javascript 
function f() {
  return 1;
}

(f) // function f(){return 1;}
f() // 1
``` 

上のコードでは、括弧の中に入れた関数は関数自身に戻り、括弧が続く関数は関数を呼び出します。

括弧の中には、式しか入れません。括弧の中に文章を入れると、エラーが発生します。

```javascript 
(var a = 1)
// SyntaxError: Unexpected token var
``` 

左結合と右結合 

同じ優先度の演算子が同時に現れた場合、計算の順序の問題があります。

```javascript 
a OP b OP c
``` 

上のコードでは`OP`は演算子を表しますこれには二つの解釈があります。

```javascript 
方式その1 
(a OP b) OP c 

//方式2 
a OP (b OP c) 
``` 

上記の2つの方法では、往々にして得られる計算結果が異なります。1つは、左の2つの演算子を結合して、このような解釈の演算子を採用して、「左結合」(left-to-right associativity)演算子と呼ばれます。2つ目は、右側の2つの演算子を結合したもので、これを「右結合」演算子(right-to-left associativity)と呼びます。

JavaScript言語のほとんどの演算子は「左結合」 。次の加算子の例を見てください。

```javascript 
x + y + z 

//エンジンは次のとおり 
(x + y) + z 
``` 

上のコードでは、`x`と`y`が結合され、それらの計算結果は`z`と演算されます。

少数の演算子は「右結合」 が、主なものは賦値演算子(`=`)と三項条件演算子(`?` 。

```javascript 
w = x = y = z;
q = a ? b : c ? d : e ? f : g;
``` 

上記のコードの解釈は以下の通り 。

```javascript 
w = (x = (y = z));
q = a ? b : (c ? d : (e ? f : g));
``` 

上の2行は右側の演算を組み合わせたもの 

また、指数演算子(`**`)も右結合 。

```javascript 
2 ** 3 ** 2 
//2 **(3 ** 2)に相当します。
// 512 
```