ECMAScript 7仕様のToPrimitive抽象的な操作
8977 ワード
本明細書では、
予備知識
ECMAScriptデータタイプ言語タイプは開発者が直接使用できるデータタイプです. 規範タイプは Udefined Null Boolean、ブールタイプ String、文字列タイプ Symbol、シンボルタイプ Number、デジタルタイプ Object、オブジェクトタイプ 元のデータタイプは、上記
@toPrimitive
ToPrimitive(input[,PrferredType])
抽象的な動作は、パラメータ
パラメータ
結果
Udefined
input自身に戻ります
Null
input自身に戻ります
ボロア
input自身に戻ります
Number
input自身に戻ります
String
input自身に戻ります
Symbol
input自身に戻ります
Object
次のステップを実行します.が もし もし は、 もし は、 は、 投げタイプエラーの異常. もし は、 Ordinary ToPrimitive(O,hint)もし もし は、各反復値 は、 もし は、 は、 投げタイプエラーの異常. 上記の操作手順で分かります.は、オプションパラメータ は、 実践
なぜ規範の抽象的な方法を説明するのかという質問があるかもしれませんが、抽象的な方法はまだ使えません.実はそうではないです.この方法は多くのところで使われます.あなたが知らないだけです.いくつかの実例を説明して、理解を深めます.
''+[1,2,3]
上記
締め括りをつける
本論文は主に
ECMAScript7
仕様におけるToPrimitive
の抽象的な動作を紹介する.予備知識
ECMAScriptデータタイプ
ECMAScript
データタイプは2種類のデータタイプに細分化されています.1つは言語タイプで、1つは規範タイプです.meta-values
(メタ値)を表し、アルゴリズムでECMAScript
言語構造および言語タイプの意味を記述するために使用される.それらは主に仕様の説明に用いられ、本当に実現される必要はない.ECMAScript
の言語タイプは全部で7種類あります.Undefined
、Null
、Boolean
、String
、Symbol
、Number
、およびList
の総称であり、非対象データタイプである.以下に関連する仕様タイプは、« »
だけであり、つまり、配列に類似したリストであり、シンボルSymbol
で表される.@toPrimitive
@@toPrimitive
には、Symbol.toPrimitive
などの多くの有名なシンボルがあります.Symbol
オブジェクトに定義されている属性の一つです.ToPrimitive(input[,PrferredType])
抽象的な動作は、パラメータ
input
とオプションのパラメータPreferredType
とを受け入れる.この抽象的な動作の目的は、パラメータinput
を非オブジェクトデータタイプ、すなわち元のデータタイプに変換することである.input
が複数の元のデータに同時に変換できる場合、PreferredType
の値を優先的に参照する.転化過程は下表を参照する.パラメータ
input
のデータタイプ結果
Udefined
input自身に戻ります
Null
input自身に戻ります
ボロア
input自身に戻ります
Number
input自身に戻ります
String
input自身に戻ります
Symbol
input自身に戻ります
Object
次のステップを実行します.
input
のデータタイプがオブジェクトである場合、以下のステップが実行される.PreferredType
パラメータに入っていない場合、hint
は"default"
に等しい.PreferredType
がhint String
であれば、hint
が"string"
に等しくなるようにする.PreferredType
がhint Number
であれば、hint
が"number"
に等しくなるようにする.exoticToPrim
をGetMethod(input, @@toPrimitive)
に等しくさせる.概ね、意味は、パラメータinput
を取得する@@toPrimitive
の方法である.exoticToPrim
がUndefined
ではないなら、result
をCall(exoticToPrim, input, « hint »)
に等しくする.exoticToPrim(hint)
が元のデータタイプである場合、result
に戻る.result
がhint
であれば、"default"
がhint
に等しくなるようにする."number"
の抽象的な動作の結果を返す.OrdinaryToPrimitive(input, hint)
のデータタイプは対象であり、O
のデータタイプは文字列であり、hint
の値はhint
であるか、"string"
であるかのいずれかである.この抽象的な操作の手順は以下の通りである."number"
がhint
であれば、"string"
がmethodNames
に等しくなるようにする.« "toString", "valueOf" »
がhint
であれば、"number"
がmethodNames
に等しくなるようにする.« "valueOf", "toString" »
について、順序で反復リストmethodNames
を反復する.name
をmethod
に等しくする.概ね、語義は、取得対象Get(O, name)
のO
値に対応する属性である.name
が起動できるなら、method
をmethod
に等しくする.Call(method, O)
のタイプがオブジェクトでない場合、method()
に戻る.result
が提供されていない場合、result
は、ToPrimitive
にデフォルトであることを6
によって知る.PreferredType
のステップhint
によって、規格で定義されている"number"
の日付オブジェクトおよびToPrimitive
のシンボルオブジェクトのいずれもがプロトタイプに4
の方法を定義するように、デフォルト動作をカバーすることができることが分かる.なぜ規範の抽象的な方法を説明するのかという質問があるかもしれませんが、抽象的な方法はまだ使えません.実はそうではないです.この方法は多くのところで使われます.あなたが知らないだけです.いくつかの実例を説明して、理解を深めます.
''+[1,2,3]
'' + [1, 2, 3] // "1,2,3"
標準の足し算操作によれば、動作@@toPrimitive
に対して、Date
およびSymbol
を呼び出して@@toPrimitive
およびx + y
を元のデータタイプに変換する.上記の例ではToPrimitive(x)
自体が元のデータタイプなので、ToPrimitive(y)
自体に戻ります.x
はオブジェクトタイプであり、配列はy
属性を定義していない.''
が提供されていないので、''
が動作するステップ[1, 2, 3]
において@@toPrimitive
がPreferredType
に変化するので、ToPrimitive
の6
はhint
である.var a = [1, 2, 3]
a.valueOf() // [1, 2, 3], a
a.toString() // "1,2,3"
"number"
は、配列OrdinaryToPrimitive
自体か、オブジェクトタイプかを返しているので、methodNames
方法を呼び出し続け、文字列« "valueOf", "toString" »
に戻ります.'' + [1, 2, 3] // => '' + '1,2,3' => '1,2,3'
この方法が元のデータタイプに戻るように配列プロトタイプ上のvalueOf
方法をカバーすると、結果はどうなるだろうか?var a = [1, 2, 3]
a.valueOf = function () {
console.log('trigger valueOf')
return 'hello'
}
'' + a // => '' + 'hello' => 'hello'
デフォルトのa
を上書きした後、呼び出しtoString
は元のデータタイプに戻ります."1,2,3"
のvalueOf
によれば、この時は直接に戻ってきます.valueOf
方法は再起動されません.また、コンソールvalueOf
からOrdinaryToPrimitive
が出ています.つまり3.2.2
は確かに呼び出されました.この方法がオブジェクトタイプに戻るように配列のデフォルトtoString
方法をカバーすると、その結果はどうなるだろうか?var a = [1, 2, 3]
a.toString = function () {
console.log('trigger toString')
return this
}
'' + a // Uncaught TypeError: Cannot convert object to primitive value
配列プロトタイプ上のlog
方法がオブジェクトタイプに戻るため、上記の例では"trigger valueOf"
をカバーし、オブジェクトタイプにも戻すことで、valueOf
のtoString
の第valueOf
のステップ、すなわちタイプエラーの異常を捨てて、対象を元のデータタイプに変換することができない.上記では、toString
方式によりOrdinaryToPrimitive
の動作をカスタマイズすることができると述べた.var a = [1, 2, 3]
a[Symbol.toPrimitive] = function () {
return 'custom'
}
'' + a // => '' + 'custom' => 'custom'
加算動作は、4
を呼び出したときに@@toPrimitive
を提供していません.次に、ToPrimitive
を優先的に使用するToPrimitive
の例として使用します.var a = [1, 2, 3]
a.valueOf = function () {
console.log('trigger valueOf')
return 'hello'
}
a.valueOf() // "hello"
a.toString() // "1,2,3"
var obj = {}
obj[a] = 'hello' // obj {1,2,3: "hello"}
変数をキーとして使用すると、キー値を元のデータタイプに変換するPreferredType
が呼び出され、hint String
の値はPreferredType
です.上記の例からも分かるように、ToPrimitive
およびPreferredType
の結果はすべて文字列であるが、hint String
を使用し、a.valueOf
を使用した結果である.もちろん、a.toString
方法を再定義し、オブジェクトに戻ると、'1,2,3'
の値が使用される.var a = [1, 2, 3]
a.valueOf = function () {
console.log('trigger valueOf')
return 'hello'
}
a.toString = function () {
console.log('trigger toString')
return this
}
var obj = {}
obj[a] = 'hello' // obj {hello: "hello"}
そして、a.toString
は、コンソールでtoString
を先に出し、valueOf
はlog
を出す.もちろん、この二つが全部対象に戻ると、エラーが発生します.var a = [1, 2, 3] // valueOf
a.toString = function () {
console.log('trigger toString')
return this
}
var obj = {}
obj[a] = 'hello' // Uncaught TypeError: Cannot convert object to primitive value
Date上記
"trigger toString"
において、log
オブジェクトおよび"trigger valueOf"
オブジェクトについては、プロトタイプにToPrimitive
方法が定義されている.Date
の第Symbol
ステップの動作では、@@toPrimitive
が提供されていないときに、優先的にToPrimitive
を呼び出す方法を見ることができる.Date原型上の@toPrimitiveによって行われることは、非常に簡単である.6
が提供されていない場合、優先的にPreferredType
方法を呼び出す.したがって、上記の動作については、valueOf
オブジェクトの動作が異なる.var a = [1, 2, 3]
a.valueOf = function () {
return 'hello'
}
a.valueOf() // "hello"
a.toString() // "1,2,3"
'' + a // "hello"
var date = new Date()
date.valueOf() // 1536416960724
date.toString() // "Sat Sep 08 2018 22:29:20 GMT+0800 ( )"
'' + date // "Sat Sep 08 2018 22:29:20 GMT+0800 ( )"
PreferredType
のtoString
方法およびDate
方法は、元のデータタイプに戻るが、優先的にdate
方法を使用することができる.締め括りをつける
本論文は主に
valueOf
の抽象的な操作と関連した例を説明します.もしこの文章に何か間違いや不備があったら、コメントエリアにコメントしてください.