Array.from के साथ कौन से वर्ण समूहीकृत हैं?


38

मैं JS के साथ खेल रहा हूँ और यह पता नहीं लगा सकता कि JS कैसे तय करता है कि उपयोग करते समय निर्मित सरणी में कौन से तत्व जोड़े जाएँ Array.from()। उदाहरण के लिए, निम्न इमोजी length, की 2 है, क्योंकि यह दो कोड बिंदुओं से बना है, लेकिन, Array.from()इन दो कोड बिंदुओं को एक मानता है, एक तत्व के साथ एक सरणी देता है:

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

हालाँकि, कुछ अन्य वर्णों में भी दो कोड बिंदु होते हैं जैसे कि यह वर्ण षि( .length2 का भी)। हालांकि, Array.fromइस चरित्र को "समूह" नहीं करता है और इसके बजाय दो तत्व पैदा करता है:

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

मेरा प्रश्न है: यह निर्धारित करता है कि क्या चरित्र टूट गया है (उदाहरण दो में) या एक एकल तत्व के रूप में माना जाता है (जैसे उदाहरण एक) जब चरित्र में दो कोड बिंदु होते हैं?


5
UTF-16 सरोगेट जोड़े पर एक नजर ...
जोनास विल्म्स


1
-S: मैं Array.from की MDN के polyfill है, जो एक अलग व्यवहार है के बारे में एक चिंता का विषय है
हाथी

1
@ यदि यह केवल वस्तुओं पर विचार करता है length। Iterators या यहां तक Setकि उस के साथ काम नहीं करता है
adiga

जवाबों:


26

Array.fromपहले तर्क के पुनरावृत्ति को आमंत्रित करने की कोशिश करता है अगर यह एक है, और तार में पुनरावृत्तियां हैं, तो यह आह्वान करता है String.prototype[Symbol.iterator], तो आइए देखें कि प्रोटोटाइप विधि कैसे काम करती है। यह यहाँ विनिर्देशन में वर्णित है :

  1. ओ हो? NeedObjectCoercible (यह मान)।
  2. रहने दो ? ToString (ओ)।
  3. CreateStringIterator (S) पर लौटें।

अवलोकन किया जा रहा CreateStringIteratorअंत में आप के लिए ले जाता है 21.1.5.2.1 %StringIteratorPrototype%.next ( ), जो करता है:

  1. Cp होने दो! CodePointAt (s, स्थिति)।
  2. परिणामी स्ट्रिंग को cp युक्त स्ट्रिंग मान हो। [[CodeUnitCount]] अनुक्रमणिका स्थिति में कोड इकाई के साथ शुरुआत से लगातार कोड इकाइयाँ।
  3. O को सेट करें। [[StringNextIndex]] को स्थिति + cp। [[CodeUnitCount]]।
  4. CreateIterResultObject (resultString, गलत) पर लौटें।

वह CodeUnitCountहै जो आप में रुचि रखते हैं। यह नंबर CodePointAt से आता है :

  1. पहले स्ट्रिंग के भीतर सूचकांक स्थिति में कोड इकाई होने दें।
  2. बता दें कि cp वह कोड पॉइंट है जिसका संख्यात्मक मान पहले होता है।
  3. यदि पहले एक प्रमुख सरोगेट या ट्रेलिंग सरोगेट नहीं है, तो

    ए। रिकॉर्ड लौटाओ { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }

  4. यदि पहले एक अनुगामी सरोगेट या स्थिति + 1 = आकार है, तो

    रिकॉर्ड दर्ज करें { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }

  5. दूसरी स्ट्रिंग के भीतर इंडेक्स स्थिति + 1 पर कोड इकाई होने दें।

  6. यदि दूसरा अनुगामी सरोगेट नहीं है, तो

    ए। रिकॉर्ड लौटाओ { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }

  7. Cp को सेट करें! UTF16DecodeSurrogatePair (पहला, दूसरा)।

  8. रिकॉर्ड लौटाओ { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }

इसलिए, जब एक स्ट्रिंग के साथ पुनरावृत्ति होती है Array.from, तो यह केवल 2 का एक कोड यूनेटिट रिटर्न देता है, जब प्रश्न में वर्ण एक सरोगेट जोड़ी की शुरुआत होता है। सरोगेट जोड़े के रूप में व्याख्या किए गए वर्ण यहां वर्णित हैं :

इस तरह के ऑपरेशन समावेशी रेंज में 0xD800 से 0xDBFF (यूनिकोड स्टैंडर्ड द्वारा एक प्रमुख सरोगेट के रूप में परिभाषित , या अधिक औपचारिक रूप से एक उच्च-सरोगेट कोड इकाई के रूप में) और हर कोड इकाई में एक संख्यात्मक मान के साथ हर कोड इकाई के लिए विशेष उपचार लागू करते हैं। निम्न नियमों का उपयोग करके समावेशी श्रेणी 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

का पहला चरित्र कोड '👍'हेक्स, डी 83 डी में है, जो 0xD800 to 0xDBFFप्रमुख सरोगेट की सीमा के भीतर है । इसके विपरीत, का पहला वर्ण कोड 'षि'बहुत कम है, और नहीं है। तो 'षि'अलग हो जाता है, लेकिन'👍' नहीं करता है।

षिदो अलग-अलग पात्रों से बना है: , देवनागरी पत्र सर्व शिक्षा अभियान , और ि, देवनागरी स्वर मैं साइन । जब इस क्रम में एक-दूसरे के बगल में होते हैं, तो वे दो अलग-अलग वर्णों से बने होने के बावजूद, नेत्रहीन रूप से एक ही वर्ण में संयोजित हो जाते हैं।

इसके विपरीत, 👍 केवल एक ग्लिफ़ के रूप में एक साथ होने पर वर्ण कोड केवल समझ में आता है। यदि आप दूसरे के बिना कोड बिंदु के साथ एक स्ट्रिंग का उपयोग करने की कोशिश करते हैं, तो आपको एक बकवास प्रतीक मिलेगा:

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


10
मुझे लगता है कि, जबकि ज्यादातर सही, उपयोगी, और सावधानीपूर्वक प्रदान किए गए उद्धरणों के साथ, यह उत्तर स्पष्ट रूप से दो मामलों के बीच महत्वपूर्ण अंतर को स्पष्ट करने में विफल रहता है: यूनिकोड के दृष्टिकोण से, षिवास्तव में दो कोड हैं जिनमें अलग-अलग कोड बिंदुओं के साथ संयुक्त रूप से एकल बनाते हैं ग्लिफ़ (एक सार चरित्र, जैसा कि मनुष्यों द्वारा समझा जाता है)। यह 👍इमोजी के विपरीत है , जो अपने आप में एक पूर्ण चरित्र है, भले ही इसका कोड बिंदु इतना अधिक है कि इसे सरोगेट जोड़ी में विभाजित करना होगा। मेरा मानना ​​है कि यह स्पष्ट करने में मदद कर सकता है (अन्यथा मूल्यवान) बहुत कुछ उत्तर दे सकता है।
राइनो

विशेष रूप से, व्यंजन ष (रों) और स्वर ि (i) रेखांकन शब्दांश में संयोजन षि (एसआई)
Amadan

@CertainPerformance "।" में केवल एक कोड बिंदु है। इससे पता चलता है कि इस उत्तर में शब्दावली गलत हो सकती है।
बेन एस्टन

13

UTF-16 (js में स्ट्रिंग्स के लिए उपयोग किया जाने वाला एन्कोडिंग) 16bit इकाइयों का उपयोग करता है। तो हर एक यूनिकोड जिसे 15 बिट का उपयोग करके दर्शाया जा सकता है, उसे एक कोड बिंदु के रूप में दर्शाया जाता है, बाकी दो को सरोगेट जोड़े के रूप में जाना जाता है । तार के इटरेटर कोड अंक से अधिक iterates।

यूटीएफ -16 विकिपीडिया पर


8

यह सभी वर्णों के पीछे के कोड के बारे में है। कुछ को दो बाइट्स (UTF-16) में कोडित किया Array.fromजाता है और दो पात्रों के रूप में व्याख्या की जाती है । पात्रों की सूची की जाँच करेगा:

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)));


फ़ंक्शन के लिए जो हेक्स कोड प्रदर्शित करता है:

जावास्क्रिप्ट: यूनिकोड स्ट्रिंग से हेक्स

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.