Array.fromでグループ化される文字は何ですか?


38

私はJSをいじっていますが、JSを使用して、作成された配列に追加する要素をJSがどのように決定するのかわかりませんArray.from()。たとえば、次の絵文字👍はlength2のコードポイントで構成されているため、2ですが、Array.from()これらの2つのコードポイントを1つとして扱い、1つの要素を持つ配列を提供します。

const emoji = '👍';
console.log(Array.from(emoji)); // Output: ["👍"]

ただし、他の一部の文字には、この文字のように2つのコードポイントがषिあります(a .lengthも2です)。ただし、Array.fromこの文字を「グループ化」せず、代わりに2つの要素を生成します。

const str = 'षि';
console.log(Array.from(str)); // Output: ["ष", "ि"]

私の質問は次のとおりです。文字が2つのコードポイントで構成されている場合、文字が分割されるか(例2のように)、または1つの要素として処理されるか(例1のように)を決定するのは何ですか。


5
UTF-16サロゲートペアを
ご覧ください


1
MDNのArray.fromのpolyfillについて懸念があります。これには別の動作があります:-s
Ele

1
@Eleはlength。イテレータまたはそれでもSet動作しない
adiga

回答:


26

Array.from最初に引数のイテレータがある場合はそれを呼び出そうとし、文字列にはイテレータがあるため、を呼び出しますString.prototype[Symbol.iterator]。プロトタイプメソッドがどのように機能するか調べてみましょう。それはここの仕様説明されています

  1. Oにしましょう RequireObjectCoercible(この値)。
  2. になろう ?ToString(O)。
  3. CreateStringIterator(S)を返します。

ルックアップCreateStringIteratorすると21.1.5.2.1 %StringIteratorPrototype%.next ( )、最終的にに移動します。

  1. cpにしよう!CodePointAt(s、position)。
  2. resultStringを、インデックス位置のコードユニットで始まる、sから連続したcp。[[CodeUnitCount]]コードユニットを含むString値とします。
  3. O。[[StringNextIndex]]を位置+ cp。[[CodeUnitCount]]に設定します。
  4. CreateIterResultObject(resultString、false)を返します。

これCodeUnitCountはあなたが興味を持っているものです。この番号はCodePointAtから取得さます

  1. 最初に文字列内のインデックス位置のコード単位とします。
  2. cpを、最初の数値であるコードポイントとする。
  3. 最初が先行サロゲートまたは後続サロゲートでない場合、

    a。レコードを返し{ [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }ます。

  4. 最初が後続サロゲートまたは位置+ 1 =サイズの場合、

    レコードを返す{ [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }

  5. 2番目を文字列内のインデックス位置+ 1のコード単位とします。

  6. 2番目が後続の代理ではない場合、

    a。レコードを返し{ [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }ます。

  7. cpを!UTF16DecodeSurrogatePair(1番目、2番目)。

  8. レコードを返し{ [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }ます。

したがって、で文字列を反復処理するArray.from場合、問題の文字がサロゲートペアの開始である場合にのみ、CodeUnitCountが2を返します。サロゲートペアとして解釈される文字は次のとおりです

このような操作は、0xD800から0xDBFFまでの範囲の数値(Unicode規格では先行サロゲートとして、またはより正式には高サロゲートコードユニットとして定義)のすべてのコードユニットと数値のすべてのコードユニットに特別な処理を適用します以下のルールを使用して、0xDC00から0xDFFFまでの範囲(後続サロゲートとして、またはより正式には低サロゲートコード単位として定義)。

षि はサロゲートペアではありません:

console.log('षि'.charCodeAt()); // First character code: 2359, or 0x937
console.log('षि'.charCodeAt(1)); // Second character code: 2367, or 0x93F

しかし👍の文字は次のとおりです。

console.log('👍'.charCodeAt()); // 55357, or 0xD83D
console.log('👍'.charCodeAt(1)); // 56397, or 0xDC4D

の最初の文字コード'👍'は、16進数でD83Dであり、これは0xD800 to 0xDBFF先行サロゲートの範囲内です。対照的に、の最初の文字コード'षि'ははるかに低く、そうではありません。したがって、'षि'分割されますが、分割され'👍'ません。

षि:二つの別々の文字で構成されデーヴァナーガリー文字Ssaの、そしてिデーヴァナーガリー母音は私に署名。この順序で隣り合うと、2つの個別の文字で構成されているにもかかわらず、視覚的に1つの文字に視覚的に結合されます。

対照的に、の文字コードは、1つのグリフとしてまとめた場合に👍 のみ意味があります。どちらか一方のコードポイントを含む文字列をもう一方の文字列なしで使用しようとすると、意味のない記号が表示されます。

console.log('👍'[0]);
console.log('👍'[1]);


10
ビューのUnicodeの点から、私は主に、正しい便利な、と慎重に提供引用して、この答えは明らかに2例の主な違いを説明するために失敗しながら、その思いषि、実際にある2つのを形成するために結合の異なるコード・ポイントを持つ文字グリフ(人間が理解できる1つの抽象文字)。これは、👍コードポイントがサロゲートペアに分割する必要があるほど高いにもかかわらず、それ自体が完全な文字である絵文字とは対照的です。これを明確にすることで、この(そうでなければ価値のある)答えをたくさん得ることができると信じています。
サイ

具体的には、子音のष(ṣ)と母音のि(i)をグラフィカルに組み合わせて音節षि(ṣi)に
アマダン

@CertainPerformance「👍」のコードポイントは1つだけです。これは、この回答の用語が正しくない可能性があることを示唆しています。
ベンアストン

13

UTF-16(jsの文字列に使用されるエンコーディング)は16ビット単位を使用します。したがって、15ビットを使用して表すことができるすべてのユニコードは1つのコードポイントとして表され、それ以外はすべて2として表されます(サロゲートペアと呼ばれます)。文字列反復子は、コードポイントを反復処理します。

ウィキペディアのUTF-16


8

それはキャラクターの背後にあるコードに関するすべてです。一部は2バイトでコード化され(UTF-16)、Array.from2つの文字として解釈されます。お奨めの文字のリストを確認してください:

http://www.fileformat.info/info/charset/UTF-8/list.htm

http://www.fileformat.info/info/charset/UTF-16/list.htm

function displayHexUnicode(s) {
  console.log(s.split("").reduce((hex,c)=>hex+=c.charCodeAt(0).toString(16).padStart(4,"0"),""));
}

displayHexUnicode('षि');

console.log(Array.from('षि').forEach(x => displayHexUnicode(x)));


function displayHexUnicode(s) {
  console.log(s.split("").reduce((hex,c)=>hex+=c.charCodeAt(0).toString(16).padStart(4,"0"),""));
}

displayHexUnicode('👍');

console.log(Array.from('👍').forEach(x => displayHexUnicode(x)));


16進コードを表示する関数の場合:

JavaScript:Unicode文字列を16進数に

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.