データ型変換
概要
JavaScript は動的に型指定される言語であり、変数には型の制限がなく、いつでも任意の値を割り当てることができます。
var x = y ? 1 : 'a';
上記のコードでは、変数 x
が数値であるか文字列であるかは、別の変数 y
の値によって決まります。 「y」が「true」の場合、「x」は数値であり、「y」が「false」の場合、「x」は文字列です。これは、コンパイル時には x
の型を知ることができず、実行時まで待たなければならないことを意味します。
変数のデータ型は未定義ですが、さまざまな演算子にはデータ型の要件があります。演算子の型が予期された型と一致しないことが判明した場合、演算子は自動的に型を変換します。たとえば、減算演算子は、左右の演算子が数値であることを想定しており、そうでない場合は自動的に数値に変換します。
'4' - '3' // 1
上記のコードでは、2 つの文字列が減算されていますが、結果値 '1' が得られます。これは、JavaScript が演算子を数値に自動的に変換するためです。
この章では、データ型の自動変換の規則について説明します。その前に、データ型を手動でキャストする方法を説明しましょう。
強制変換
強制変換とは主に、「Number()」、「String()」、「Boolean()」の 3 つの関数を使用して、さまざまな種類の値をそれぞれ数値、文字列、またはブール値に手動で変換することを指します。
###番号()
「Number」関数を使用すると、あらゆる種類の値を数値に変換できます。
以下の説明は 2 つの場合に分けられます。1 つはパラメーターがプリミティブ型の値である場合、もう 1 つはパラメーターがオブジェクトである場合です。
(1) プリミティブ型の値
プリミティブ型の値の変換規則は以下のとおりです。
//数値: 変換後も元の値
数値(324) // 324
// 文字列: 数値として解析できる場合は、対応する数値に変換します
Number('324') // 324
// 文字列: 数値として解析できない場合は、NaN を返します。
Number('324abc') // NaN
// 空の文字列を 0 に変換します
数値('') // 0
// ブール値: true は 1 に変換され、false は 0 に変換されます。
数値(真) // 1
数値(偽) // 0
// 未定義: NaN に変換されます
数値(未定義) // NaN
// null: 0に変換
数値(null) // 0
Number
関数は文字列を数値に変換し、parseInt
関数よりもはるかに厳密です。基本的に、1 文字が数値に変換できない限り、文字列全体が NaN
に変換されます。
parseInt('42 猫') // 42
Number('42 猫') // NaN
上記のコードでは、parseInt
が文字を 1 つずつ解析し、Number
関数が文字列全体の型を変換します。
さらに、「parseInt」関数と「Number」関数は両方とも、文字列内の先頭と末尾のスペースを自動的にフィルタリングします。
parseInt('\t\v\r12.34\n') // 12
Number('\t\v\r12.34\n') // 12.34
(2)オブジェクト
単純なルールは、Number
メソッドのパラメータがオブジェクトの場合、それが単一の値を含む配列でない限り、NaN
を返すということです。
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
数値([5]) // 5
その理由は、「Number」の背後にある変換ルールがより複雑であるためです。
最初のステップは、オブジェクト自体の valueOf
メソッドを呼び出すことです。プリミティブ型の値が返された場合は、それ以上の手順を実行せずに、値に対して直接 Number
関数を使用します。
2 番目のステップでは、valueOf
メソッドが依然としてオブジェクトを返す場合、代わりにオブジェクト自体の toString
メソッドが呼び出されます。 toString
メソッドがプリミティブ型の値を返した場合、その値に対して Number
関数が使用され、それ以上の手順は実行されません。
3 番目のステップは、「toString」メソッドがオブジェクトを返した場合にエラーを報告することです。
以下の例を参照してください。
var obj = {x: 1};
Number(obj) // NaN
// と同等
if (typeof obj.valueOf() === 'オブジェクト') {
Number(obj.toString());
} それ以外 {
Number(obj.valueOf());
}
上記のコードでは、Number
関数が obj
オブジェクトを数値に変換します。一連の操作がバックグラウンドで行われ、最初に obj.valueOf
メソッドが呼び出され、結果がオブジェクト自体に返され、次に obj.toString
メソッドが呼び出され、文字列 が返されます。 [object Object]
が返されました。この文字列 Number関数に
を使用すると、NaN
が得られます。
デフォルトでは、オブジェクトの valueOf
メソッドはオブジェクト自体を返すため、常に toString
メソッドが呼び出され、 toString
メソッドはオブジェクトの型文字列 ([object Object]
など) を返します。したがって、次のような結果が得られます。
Number({}) // NaN
toString
メソッドがプリミティブ型ではない値を返した場合、エラーが報告されます。
var obj = {
値の: 関数 () {
戻る {};
}、
toString: function () {
戻る {};
}
};
数値(オブジェクト)
// TypeError: オブジェクトをプリミティブ値に変換できません
上記のコードの valueOf
メソッドと toString
メソッドはオブジェクトを返すため、それらを数値に変換するときにエラーが報告されます。
上記の例から、「valueOf」メソッドと「toString」メソッドをカスタマイズできることもわかります。
番号({
値の: 関数 () {
2を返します。
}
})
// 2
番号({
toString: function () {
3 を返します。
}
})
// 3
番号({
valueOf: 関数 () {
2を返します。
}、
toString: function () {
3 を返します。
}
})
// 2
上記のコードは 3 つのオブジェクトに対して Number
関数を使用しています。最初のオブジェクトは valueOf
メソッドの値を返し、2 番目のオブジェクトは toString
メソッドの値を返し、3 番目のオブジェクトは valueOf
メソッドが toString
メソッドの前に実行されることを示します。
弦()
String
関数は、任意の型の値を文字列に変換できます。変換規則は次のとおりです。
(1) プリミティブ型の値
- 値: 対応する文字列に変換します。
- 文字列: 変換後も元の値が残ります。
- ブール値:
true
は文字列"true"
に変換され、false
は文字列"false"
に変換されます。 - 未定義: 文字列
"未定義"
に変換します。 - null: 文字列
"null"
に変換します。
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
文字列(未定義) // "未定義"
String(null) // "null"
(2)オブジェクト
String
メソッドのパラメータがオブジェクトの場合は文字列型を返し、配列の場合は配列の文字列形式を返します。
String({a: 1}) // "[オブジェクト オブジェクト]"
String([1, 2, 3]) // "1,2,3"
String
メソッドの背後にある変換規則は、valueOf
メソッドと toString
メソッドの実行順序が入れ替わることを除いて、基本的には Number
メソッドと同じです。
-
まず、オブジェクト自体の
toString
メソッドを呼び出します。プリミティブ型の値が返された場合は、その値に対してString
関数を使用し、次の手順には進まないでください。 -
toString
メソッドがオブジェクトを返した場合は、元のオブジェクトのvalueOf
メソッドを呼び出します。valueOf
メソッドがプリミティブ型の値を返す場合は、その値に対してString
関数を使用し、次の手順には進まないでください。 -
valueOf
メソッドがオブジェクトを返す場合、エラーが報告されます。
以下に例を示します。
文字列({a:1})
// "[オブジェクト オブジェクト]"
// と同等
文字列({a: 1}.toString())
// "[オブジェクト オブジェクト]"
上記のコードは、最初にオブジェクトの toString
メソッドを呼び出し、文字列 [object Object]
が返されることがわかるため、今後は valueOf
メソッドを呼び出しません。
toString
メソッドと valueOf
メソッドがオブジェクトを返す場合、エラーが報告されます。
var obj = {
値の: 関数 () {
戻る {};
}、
toString: function () {
戻る {};
}
};
文字列(オブジェクト)
// TypeError: オブジェクトをプリミティブ値に変換できません
以下はtoStringメソッドをカスタマイズして戻り値を変更する例です。
弦({
toString: function () {
3 を返します。
}
})
//「3」
弦({
値の: 関数 () {
2を返します。
}
})
// "[オブジェクト オブジェクト]"
弦({
値の: 関数 () {
2を返します。
}、
toString: function () {
3 を返します。
}
})
//「3」
上記のコードは 3 つのオブジェクトに対して String
関数を使用しています。最初のオブジェクトは toString
メソッドの値 (値 3) を返し、2 番目のオブジェクトは toString
メソッドの値 ([object Object]
) を返し、3 番目のオブジェクトは toString
メソッドが先行することを示します。 valueOf
メソッドが実行されます。
###ブール値()
Boolean()
関数は、あらゆるタイプの値をブール値に変換できます。
変換ルールは比較的単純で、以下の5つの値を除いて変換結果は「false」、その他の値はすべて「true」となります。
- 「未定義」
- 「ヌル」
0
(-0
および+0
を含む)- 'NaN'
''
(空の文字列)
Boolean(未定義) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
もちろん、「true」と「false」の 2 つのブール値は変わりません。
Boolean(true) // true
Boolean(false) // false
すべてのオブジェクト (空のオブジェクトを含む) の変換結果は true
であり、false
に対応するブール型オブジェクト new Boolean(false)
も true
であることに注意してください (「プリミティブ型値のオブジェクトのパッケージ化」を参照)詳細については章を参照してください)。
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
すべてのオブジェクトのブール値は「true」です。これは、JavaScript 言語の設計時に、「obj1 && obj2」のようなシナリオでブール値を取得するためにオブジェクトを計算する必要があるためです。さらに計算が必要になる場合があります。性能を保証するため、オブジェクトのブール値は「true」であることが一律に規定されている。
自動変換
以下に強制変換をベースとした自動変換を紹介します。
次の 3 つの状況が発生した場合、JavaScript はデータ型を自動的に変換します。つまり、変換は自動的に完了し、ユーザーには見えません。
最初のケースでは、異なるタイプのデータが相互に作用します。
123 + 'abc' // "123abc"
2 番目のケースでは、非ブール型のデータに対してブール値が計算されます。
if ('abc') {
console.log('こんにちは')
} // "こんにちは"
3 番目のケースでは、単項演算子 (つまり、「+」と「-」) が数値以外の値に使用されます。
+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
自動変換のルールは次のとおりです。期待される値のタイプに関係なく、そのタイプの変換関数を呼び出します。たとえば、特定の位置が文字列であると予想される場合は、「String()」関数を呼び出してそれを変換します。位置が文字列または数値の場合、デフォルトで数値に変換されます。
自動変換は不確実でデバッグが難しいため、ブール値、数値、文字列が期待される場合は Boolean()
、Number()
、および String()
関数を使用することをお勧めします。
ブール値に自動的に変換します
JavaScript は、ブール値が期待される場所 (「if」 ステートメントの条件部分など) に遭遇すると、非ブール値パラメーターをブール値に自動的に変換します。 Boolean()
関数はシステムによって内部的に自動的に呼び出されます。
したがって、次の 5 つの値を除いて、他のすべての値は自動的に「true」に変換されます。
- 「未定義」
- 「ヌル」
+0
または-0
- 'NaN'
''
(空の文字列)
次の例では、条件部分の各値は 'false' に相当し、否定演算子を使用すると 'true' になります。
if (!未定義
&& !null
&& !0
&& !NaN
&&!」
) {
console.log('true');
} // 真実
式をブール値に変換するには、次の 2 つの記述方法が使用されることがあります。また、内部的に Boolean()
関数も呼び出します。
//書き方その1
式 ? true : false
//書き方2
!!表現
自動的に文字列に変換されます
JavaScript は、予期される文字列を検出すると、文字列以外の値を文字列に自動的に変換します。具体的なルールは、まず複合型の値をプリミティブ型の値に変換し、次にプリミティブ型の値を文字列に変換することです。
文字列の自動変換は主に文字列の追加操作中に発生します。一方の値が文字列で、もう一方の値が文字列以外の場合、後者は文字列に変換されます。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[オブジェクト オブジェクト]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + 未定義 // "5未定義"
'5' + null // "5null"
この自動変換ではエラーが発生しやすくなります。
var obj = {
幅: '100'
};
obj.width + 20 // "10020"
上記のコードでは、開発者は「120」を返すことを期待しているかもしれませんが、自動変換により、実際には文字「10020」が返されます。
数値に自動変換
JavaScript は数値を検出すると、パラメータ値を数値に自動的に変換します。 Number()
関数はシステムによって内部的に自動的に呼び出されます。
演算子を文字列に変換する加算演算子 (+
) を除き、他の演算子は自動的に演算子を数値に変換します。
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1
未定義 + 1 // NaN
上記のコードでは、演算子の両側の演算子が数値に変換されます。
注: 数値に変換する場合、「null」は「0」に変換され、「未定義」を数値に変換する場合、「NaN」は数値に変換されます。
単項演算子も演算子を数値に変換します。
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
参考リンク
- Axel Rauschmayer、JavaScript の {} + {} とは何ですか?
- Axel Rauschmayer、JavaScript の癖 1: 値の暗黙的な変換
- ベンジー・ギラム、Quantum JavaScript?
作者: wangdoc
アドレス: https://wangdoc.com/
ライセンス: クリエイティブ・コモンズ 3.0