String.prototype.codePointAt()和String.fromCodePoint()

String.prototype.codePointAt()javascript

codePointAt()方法返回一個 Unicode 編碼點值的非負整數。java

這是一個ES6方法。數組

str.codePointAt(pos)

posapp

pos參數是字符串中字符的位置。this

若是在指定的位置沒有元素則返回 undefined 。若是在索引處開始沒有UTF-16 代理對,將直接返回在那個索引處的編碼單元。編碼

Surrogate Pair是UTF-16中用於擴展字符而使用的編碼方式,是一種採用四個字節(兩個UTF-16編碼)來表示一個字符,稱做代理對spa

'ABC'.codePointAt(1);          // 66
'\uD800\uDC00'.codePointAt(0); // 65536

'XYZ'.codePointAt(42); // undefined

polyfillprototype

if (!String.prototype.codePointAt) {
  (function() {
    'use strict'; // 嚴格模式,needed to support `apply`/`call` with `undefined`/`null`
    var codePointAt = function(position) {
      if (this == null) {
        throw TypeError();
      }
      var string = String(this);//this格式轉換字符串
      var size = string.length;//字符串長度
      // 變成整數
      var index = position ? Number(position) : 0;//position轉換成數字
      if (index != index) { // better `isNaN`判斷是否是NaN,若是是NaN,就變成0
        index = 0;
      }
      // 邊界
      if (index < 0 || index >= size) {//若是位置超出字符串邊界,就返回undefined
        return undefined;
      }
      // 第一個編碼單元
      var first = string.charCodeAt(index);//獲取位置編碼
      var second;
      if ( // 檢查是否開始 surrogate pair
        first >= 0xD800 && first <= 0xDBFF && // high surrogate若是是高半區字符而且還有下一個字符
        size > index + 1 // 下一個編碼單元
      ) {
        second = string.charCodeAt(index + 1);//獲取緊跟着的字符編碼
        if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate若是是低半區
          // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
          return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;//轉碼成輔助區字符unicode編碼
        }
      }
      return first;//若是沒有低半區字符,就返回原位置的編碼
    };
    if (Object.defineProperty) {
      Object.defineProperty(String.prototype, 'codePointAt', {
        'value': codePointAt,
        'configurable': true,
        'writable': true
      });
    } else {
      String.prototype.codePointAt = codePointAt;
    }
  }());
}

String.fromCodePoint()代理

String.fromCodePoint() 靜態方法返回使用指定的代碼點序列建立的字符串。code

這是一個ES6方法。

參數是一串unicode編碼,返回unicode對應的字符串。

若是傳入無效的 Unicode 編碼,將會拋出一個RangeError (例如: "RangeError: NaN is not a valid code point")。

String.fromCodePoint(42);       // "*"
String.fromCodePoint(65, 90);   // "AZ"
String.fromCodePoint(0x404);    // "\u0404"
String.fromCodePoint(0x2F804);  // "\uD87E\uDC04"
String.fromCodePoint(194564);   // "\uD87E\uDC04"
String.fromCodePoint(0x1D306, 0x61, 0x1D307) // "\uD834\uDF06a\uD834\uDF07"

String.fromCodePoint('_');      // RangeError
String.fromCodePoint(Infinity); // RangeError
String.fromCodePoint(-1);       // RangeError
String.fromCodePoint(3.14);     // RangeError
String.fromCodePoint(3e-2);     // RangeError
String.fromCodePoint(NaN);      // RangeError

// String.fromCharCode() 方法不能單獨獲取在高代碼點位上的字符
// 另外一方面,下列的示例中,能夠返回 4 字節,也能夠返回 2 字節的字符
// (即,它能夠返回單獨的字符,使用長度 2 代替 1!) 
console.log(String.fromCodePoint(0x2F804)); // or 194564 in decimal

polyfill

if (!String.fromCodePoint) {
  (function() {
    var defineProperty = (function() {
      // IE 8 only supports `Object.defineProperty` on DOM elements
      try {
        var object = {};
        var $defineProperty = Object.defineProperty;
        var result = $defineProperty(object, object, object) && $defineProperty;
      } catch(error) {}
      return result;
    }());
    var stringFromCharCode = String.fromCharCode;
    var floor = Math.floor;
    var fromCodePoint = function() {
      var MAX_SIZE = 0x4000;
      var codeUnits = [];
      var highSurrogate;
      var lowSurrogate;
      var index = -1;
      var length = arguments.length;
      if (!length) {//沒有傳參數返回空字符串
        return '';
      }
      var result = '';
      while (++index < length) {//循環參數數組
        var codePoint = Number(arguments[index]);//參數轉換成數字
        if (
          !isFinite(codePoint) ||       // `NaN`, `+Infinity`, or `-Infinity`
          codePoint < 0 ||              // not a valid Unicode code point
          codePoint > 0x10FFFF ||       // not a valid Unicode code point
          floor(codePoint) != codePoint // not an integer
        ) {
          throw RangeError('Invalid code point: ' + codePoint);//若是參數不符合要求就拋出錯誤
        }
        if (codePoint <= 0xFFFF) { // BMP code point 若是是基礎平面字符
          codeUnits.push(codePoint);//存入codeUnits數組
        } else { // Astral code point; split in surrogate halves 若是是輔助平面字符,計算出高半區和低半區而後存入codeUnits
          // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
          codePoint -= 0x10000;
          highSurrogate = (codePoint >> 10) + 0xD800;
          lowSurrogate = (codePoint % 0x400) + 0xDC00;
          codeUnits.push(highSurrogate, lowSurrogate);
        }
        if (index + 1 == length || codeUnits.length > MAX_SIZE) {//???這裏MAX_SIZE是什麼意思
          result += stringFromCharCode.apply(null, codeUnits);//使用fromCharCode獲取結果字符串鏈接到result後面
          codeUnits.length = 0;
        }
      }
      return result;
    };
    if (defineProperty) {
      defineProperty(String, 'fromCodePoint', {
        'value': fromCodePoint,
        'configurable': true,
        'writable': true
      });
    } else {
      String.fromCodePoint = fromCodePoint;
    }
  }());
}
相關文章
相關標籤/搜索