ECMAScript7仕様におけるToPrimitive抽象演算の知識の詳細説明(例)

不言
リリース: 2018-09-17 14:53:07
オリジナル
4623 人が閲覧しました

この記事では、ECMAScript7 仕様の ToPrimitive 抽象操作の詳細な分析 (例) を紹介します。必要な方は参考にしていただければ幸いです。

この記事では、ECMAScript7 仕様の ToPrimitive 抽象操作を紹介します。

予備知識

ECMAScript データ型

ECMAScript データ型は、データ型の 2 つの主要カテゴリに分類されます。1 つは言語タイプで、もう 1 つは仕様タイプです。

言語タイプは、開発者が直接使用できるデータタイプです。

正規タイプは、ECMAScript 言語のセマンティクスを記述するアルゴリズムで使用されるメタ値 (メタ値) を表します。構造と言語の種類。これらは主に仕様の説明に使用され、実際に実装する必要はありません。

ECMAScript には 7 つの言語タイプがあります:

Unknown

Null

Boolean、Boolean 型

String、string 型

Symbol、シンボル タイプ

Number、数値タイプ

Object、オブジェクト タイプ

元のデータ型は上記の Unknown、Null、Boolean、String、Symbol です。および Number は非オブジェクト データ型です。
以下で説明する標準タイプは List のみです。これは、記号 « » で表される、配列に似たリストです。

@@toPrimitive

Symbol には、@@toPrimitive などの有名なシンボルが多数あります。これは、Symbol オブジェクトで定義された属性である Symbol.toPrimitive です。

ToPrimitive(input [, PreferredType])

この抽象操作は、パラメーター入力とオプションのパラメーター PreferredType を受け入れます。この抽象操作の目的は、パラメーター入力を非オブジェクト データ型、つまりプリミティブ データ型に変換することです。入力を同時に複数の生データに変換できる場合は、PreferredType の値が最初に参照されます。変換プロセスについては、次の表を参照してください。

パラメータのデータ型 input Result
未定義 入力そのものを返す
Null 入力自体を返す
Boolean 入力そのものを返す
Number 入力自体を返す
文字列 入力そのものを返す
シンボル 入力そのものを返す
オブジェクト 次の手順を実行します。
#

入力データ型がオブジェクトの場合は、次の手順を実行します。

1. PreferredType パラメーターが渡されない場合は、ヒントを「default」にします。 PreferredType がヒント文字列である場合、ヒントは「string」と等しくなります。PreferredType がヒント Number である場合、ヒントは「number」と等しくなります。 GetMethod(input, @@toPrimitive)、おおよそのセマンティクスは、パラメーター入力を取得するための @@toPrimitive メソッドです。exoticToPrim が未定義でない場合は、次のようになります。 Call(exoticToPrim, input, « ヒント »)、おおよそのセマンティクスは次のとおりです。 Execute exoticToPrim(hint);

結果がプリミティブ データ型の場合、結果を返します。エラーの型を返します。 ;

6. ヒントが「デフォルト」の場合は、ヒントを「数値」にします。 OrdinaryToPrimitive(input,hint) 抽象演算の結果を返します。

OrdinaryToPrimitive(O, ヒント)

O のデータ型はオブジェクト、ヒントのデータ型は文字列、ヒントの値は「文字列」または「数値」のいずれかです。この抽象操作の手順は次のとおりです。

1. ヒントが "string" の場合、methodNames は « "toString", "valueOf" » となります。数値", メソッド名を « "valueOf", "toString" » に等しくします;

3. 反復値の名前ごとに、メソッド名のリストを順番に繰り返します:

メソッドを Call(メソッドと等しくする) , O)、おおよそのセマンティクスは、method() を実行することです。

結果の型がオブジェクトでない場合は、メソッドを Get(O, name) に戻します。おおよそのセマンティクスは、オブジェクト O 属性に対応する名前の値を取得することです。

メソッドを呼び出すことができる場合、

4 間違ったタイプの例外をスローします。

上記の手順からわかります:

ToPrimitive の手順 6 から、オプションのパラメーター PreferredType が指定されていない場合、ヒントはデフォルトで "number" になることがわかります。

#合格 ToPrimitive のステップ 4 は、@@toPrimitive メソッドを定義することでデフォルトの動作をオーバーライドできることを示しています。たとえば、仕様で定義されている Date オブジェクトと Symbol オブジェクトの両方には、プロトタイプで @@toPrimitive メソッドが定義されています。

実践

なぜ仕様で抽象メソッドを説明する必要があるのか​​と疑問に思う人もいるかもしれません。私は抽象メソッドを使用しません。実はこの方法は色々なところで使われているのに、意外と知られていないだけなのです。以下に、理解を深めるためにいくつかの例を説明します。

'' [1, 2, 3]

'' + [1, 2, 3] // "1,2,3"
ログイン後にコピー
仕様の加算演算によると、演算 x y に対して、ToPrimitive(x) と ToPrimitive(y) が呼び出されて変換されます。 x と y をプリミティブ データ型に変換します。上記の例では、'' 自体がプリミティブ データ型であるため、'' 自体が返されます。 [1, 2, 3] はオブジェクト型であり、配列では @@toPrimitive プロパティが定義されていません。 PreferredType が指定されていないため、ToPrimitive 操作のステップ 6 ではヒントは「number」になり、OrdinaryToPrimitive のメソッド名は « "valueOf", "toString" » になります。

var a = [1, 2, 3]
a.valueOf() // [1, 2, 3],数组a本身
a.toString() // "1,2,3"
ログイン後にコピー
valueOf は配列 a 自体またはオブジェクト型を返すため、toString メソッドは引き続き呼び出され、文字列 "1,2,3" が返されるため、

'' + [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'
ログイン後にコピー
デフォルトの valueOf をオーバーライドした後、valueOf を呼び出すと、元のデータ型が返されます。 OrdinaryToPrimitive の 3.2.2 によれば、この時点で直接戻り、再び toString メソッドが呼び出されることはありません。同時に、「trigger valueOf」がコンソールに記録されます。これは、valueOf が実際に呼び出されたことを意味します。

それでは、配列のデフォルトの toString メソッドをオーバーライドして、メソッドがオブジェクト型を返すようにすると、結果はどうなるでしょうか?

var a = [1, 2, 3]
a.toString = function () {
    console.log('trigger toString')
    return this
}
'' + a // Uncaught TypeError: Cannot convert object to primitive value
ログイン後にコピー

配列プロトタイプの valueOf メソッドはオブジェクト タイプを返すため、上記の例では、オブジェクト タイプも返すように toString を上書きします。その後、OrdinaryToPrimitive のステップ 4 に直接進みます。型エラー例外がスローされるだけで、オブジェクトを元のデータ型に変換できません。

次の例のように、@@toPrimitive メソッドを使用して ToPrimitive の動作をカスタマイズできることを上で説明しました。

var a = [1, 2, 3]
a[Symbol.toPrimitive] = function () {
    return 'custom'
}
'' + a // => '' + 'custom' => 'custom'
ログイン後にコピー
ToPrimitive を呼び出すときに追加操作では PreferredType が提供されません。それについて説明しましょう。次に、ヒント String を PreferredType として優先的に使用する例:

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"}
ログイン後にコピー

変数をキー値として使用する場合、ToPrimitive が呼び出されてキー値を元のデータ型に変換し、PreferredType の値はヒント String になります。 。上記の例から、a.valueOf と a.toString の結果は両方とも文字列ですが、a.toString を使用した結果である '1,2,3' が使用されていることがわかります。もちろん、toString メソッドを再定義してオブジェクトを返す場合は、valueOf の値が使用されます:

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"}
ログイン後にコピー
と、最初に「trigger toString」がコンソールに記録され、次に「trigger valueOf」が記録されます。ログに記録されます。もちろん、これらの両方がオブジェクトを返した場合でも、エラーが報告されます:

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

在上面讲ToPrimitive的时候,提到Date对象和Symbol对象在原型上定义了@@toPrimitive方法。在ToPrimitive的第6步的操作中,我们可以看到当没有提供PreferredType的时候,优先调用valueOf方法。Date原型上的@@toPrimitive做的事情非常简单:当没有提供PreferredType的时候,优先调用toString方法。所以对于上面的操作,Date对象的行为是不一样的:

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 (中国标准时间)"
ログイン後にコピー

我们可以看到date的valueOf方法和toString方法都返回原始数据类型,但是优先使用了toString方法。

总结

本文主要讲解了ToPrimitive抽象操作,以及一些相关的例子,希望大家能有所收获。

以上がECMAScript7仕様におけるToPrimitive抽象演算の知識の詳細説明(例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート