JavaScript 系列--JavaScript一些奇淫技巧的實現方法(二)數字格式化;類數組轉數組

一、前言

之前寫了一篇文章:JavaScript 系列--JavaScript一些奇淫技巧的實現方法(一)簡短的sleep函數,獲取時間戳

https://www.mwcxs.top/page/74...

介紹了sleep函數和獲取時間戳的方法。接下來我們來介紹數字格式化1234567890 --> 1,234,567,890

二、數字格式化 1234567890 --> 1,234,567,890

1、普通版

// 數字格式化 1234567890 --> 1,234,567,890
function formatNumber(str){
    var arr = [];
    var count = str.length;
    while(count>=3){
        arr.unshift(str.slice(count - 3, count));
        count -= 3;
    }
    // 如果是不是3的倍數就另外追加到上去
    str.length % 3 && arr.unshift(str.slice(0, str.length % 3));
    return arr.toString();
}
formatNumber('1234567890')

優點:自我感覺比網上寫的一堆 for循環 還有 if-else 判斷的邏輯更加清晰直白。
缺點:太普通

2、進階版

// 2、進階版
function formatNumber(str){
    return str.split("").reverse().reduce((prev,next,index) => {
        return ((index%3)? next: (next+',')) + prev;
    })
}
formatNumber("1234567890");

優點:把 JS 的 API 玩的瞭如指掌
缺點:不好理解

3、正則版

function formatNumber(str){
    return str.replace(/(?!^)(?=(\d{3})+$)/g,',')
}
formatNumber("1234567890");

我們來看看正則的分析:

(1)/(?!^)(?=(d{3})+b)/g:匹配的這個位置不能是開頭(?!^)

(2)(d{3})+:必須是1個或者多個的3個連續數字

優點:代碼少,簡潔。

缺點:正則表達式的位置匹配很重要,可以參考這個:https://www.mwcxs.top/page/58...

4、API版本

(1234567890).toLocaleString('en-us');
(1234567890).toLocaleString();
1234567890..toLocaleString();

你可能還不知道 JavaScript 的 toLocaleString 還可以這麼玩。

123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三四五六七八九"
123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三,四五六,七八九"
new Date().toLocaleString('zh-hans-cn-u-nu-hanidec'); //"二〇一九/五/二九 下午三:一五:四〇"

還可以使用Intl對象,

Intl 對象是 ECMAScript 國際化 API 的一個命名空間,它提供了精確的字符串對比,數字格式化,日期和時間格式化。Collator,NumberFormat 和 DateTimeFormat 對象的構造函數是 Intl 對象的屬性。

new Intl.NumberFormat().format(1234567890) // 1,234,567,890
優點:簡單粗暴,直接調用api

缺點:Intl兼容性不太好,不過 toLocaleString的話 IE6 都支持

前端知識點:Intl對象 和 toLocaleString的方法。

三、argruments 對象(類數組)轉換成數組

那什麼是類數組?就是跟數組很像,但是他是對象,格式像數組所以叫類數組。比如:{0:a,1:b,2:c,length:3},按照數組下標排序的對象,還有一個length的屬性,有時候我們需要這種對象能調用數組下的一個方法,這時候就需要把把類數組轉化成真正的數組。

1、普通版

var makeArray = function(arr){
    var res = [];
    if(arr != null){
        var i = arr.length;
        if(i == null || typeof arr == "string") res[0] = arr;
        else while(i){res[--i] = arr[i];}
    }
    return res;
};
var obj = {0:'a',1:'b',2:'c',length:3};
makeArray(obj);

優點:通用版本,沒有任何兼容性問題
缺點:暫時沒有啥缺點

2、進階版

// 2、進階版
var arr = Array.prototype.slice.call(arguments);

大家用過最常用的方法,至於爲什麼可以這麼用,很多人估計也是一知半解,要搞清爲什麼裏面的原因,我們還是從規範和源碼說起。

slice.call 的作用原理就是,利用 call,將 slice 的方法作用於 arrayLike,slice 的兩個參數爲空,slice 內部解析使得 arguments.lengt 等於0的時候 相當於處理 slice(0) : 即選擇整個數組,slice 方法內部沒有強制判斷必須是 Array 類型,slice 返回的是新建的數組(使用循環取值)”,所以這樣就實現了類數組到數組的轉化,call 這個神奇的方法、slice 的處理缺一不可。

直接看 slice 怎麼實現的吧。其實就是將 array-like 對象通過下標操作放進了新的 Array 裏面,下面是源碼

// This will work for genuine arrays, array-like objects, 
    // NamedNodeMap (attributes, entities, notations),
    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
    Array.prototype.slice = function(begin, end) {
      // IE < 9 gets unhappy with an undefined end argument
      end = (typeof end !== 'undefined') ? end : this.length;

      // For native Array objects, we use the native slice function
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }

      // For array like object we handle it ourselves.
      var i, cloned = [],
        size, len = this.length;

      // Handle negative value for "begin"
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);

      // Handle negative value for "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }
      // Actual expected size of the slice
      size = upTo - start;
      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };

優點:最常用的版本,兼容性強。

缺點:ie 低版本,無法處理 dom 集合的 slice call 轉數組。

3、ES6版

使用 Array.from, 值需要對象有 length 屬性, 就可以轉換成數組。

var arr = Array.from(arguments);

擴展運算符

var args = [...arguments];

ES6 中的擴展運算符...也能將某些數據結構轉換成數組,這種數據結構必須有便利器接口。

優點:直接使用內置 API,簡單易維護
缺點:兼容性,使用 babel 的 profill 轉化可能使代碼變多,文件包變大

前端知識點:slice 方法的具體原理

【注:我是saucxs,也叫songEagle,鬆寶寫代碼,文章首發於sau交流學習社區(https://www.mwcxs.top),關注我們每天閱讀更多精彩內容】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章