javascript常用工具関数のまとめ

11781 ワード

前言
  • 以下のコードは、自分で書いたもの、作業項目の枠組みの中で使われたもの、その他のフレームのソースコード、ネットで見られたものです.
  • は主にツール関数として機能し、フレームワークにサービスを提供し、自身は他のフレームクラスに依存せず、部分的にはes 6/s 7の構文に使用する場合はトランスコード
  • に注意してください.
  • は、できるだけ関数内でエラーの処理をしましたが、エラーが発生する可能性があります.
    1.url上のパラメータを取得する
      /**
       *  url    
       * @return {object}
       * @example
       * getRequest()  getRequest().paramA
       */
    function getRequest() {
        var searchString = window.location.search.substring(1),
            params = searchString.split("&"),
            hash = {};
        if (searchString == "") return {};
        for (var i = 0; i < params.length; i++) {
            var pos = params[i].indexOf('=');
            if (pos == -1) { continue; }
            var paraName = params[i].substring(0, pos),
                paraValue = params[i].substring(pos + 1);
            hash[paraName] = paraValue;
        }
        return hash;
    }
    
  • は1つのオブジェクトに戻り、url上のパラメータをキーのペアとして記憶し、urlにパラメータがない場合は、空のオブジェクト
  • に戻る.
    2.urlパラメータを追加する
      /**
       *   url  
       * @param {string} url url  
       * @param {string|object} key       
       * @param {string} value  
       * @return {string}     url
       * @example
       * appendQuery('lechebang.com', 'id', 3);
       * appendQuery('lechebang.com?key=value', { cityId: 2, cityName: '  '});
       */
      function appendQuery (url, key, value) {
        var options = key;
        if (typeof options == 'string') {
          options = {};
          options[key] = value;
        }
        options = $.param(options);
        if (url.includes('?')) {
          url += '&' + options
        } else {
          url += '?' + options
        }
        return url;
      }
    
  • は1つのurlに入ってきて、加えたいパラメータのキーパッドのペアが必要です.追加したいパラメータは直接にオブジェクトのフォーマットに伝えられます.元urlにパラメータがあるかどうかを判断します.ないと'を追加します.パラメータを追加したurlを返します.
  • 3.2つの日付の時間差を計算します.
      /**
       *             
       * @param {Date, Date}  date1 date2
       * @return {object | null} 
       * @example
       * getDiff(new Date('2017-09-08'), new Date())
       */
    function getDiff(date1, date2) {
         if (!date1.getTime || !date2.getTime) return null
         var ms = (date1.getTime() - date2.getTime());
         var day1 = Math.round(ms / 24 / 3600 / 1000),
             hh1 = Math.round((ms / 3600 / 1000) % 24),
             mm1 = Math.round((ms / 1000 / 60) % 60),
             ss1 = Math.round((ms / 1000) % 60);
         return {
             day: day1,
             hour: hh1,
             minute: mm1,
             second: ss1
          };
    }
    
  • は、2つのDate日付オブジェクトに伝えられ、1つのオブジェクトに戻り、その属性値day、hour、minute、secondは、それぞれ、日数、時間、分、秒を表す.結果はMath.round()で整理され、結果が負であれば、第一の日付が第二の日付の前にあることを示す
  • .
    4.canvasをイメージ画像フォーマットに変換する
      /**
       *  canvas   image  
       * @param {string}  cId
       * @return {object HTMLImageElement} 
       * @example
       * canvasToImg('canvas')  canvasToImg('#canvarsId')
       */
    function canvasToImg(cId){
        let canvas = document.querySelector(cId)
        if (!canvas || !canvas.toDataURL) return new Image()
        let imgData = canvas.toDataURL('image/png'),
            imgs= new Image();
            imgs.src=imgData;
        return imgs
    }
    
  • は、セレクタに従ってcanvasノードを調べ、canvasのimageフォーマットノードに戻ってきます.もし見つけられないなら、空いているイメージを返します.canvasをbase 64符号化に変換するという原理で、toData URL方法はcanvasノードだけが持っているようです.そしてsrcを新たに作成するのはこのbase 64符号化された画像です.
  • ps:どのような場合にこのような変換が必要ですか?今知っているのはcanvasが携帯端末で長押しすることができません.
  • 5.ランダムguidを生成する
      /**
       *        guid
       * @return {string}
       * @example
       * // 7f603b20-17ff-4f47-aeb9-e7996de04939
       * util.guid();
       * @see http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
       */
      function guid () {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
          var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
          return v.toString(16);
        });
      }
    
  • この方法は、ランダムguidを生成するために用いられ、生成されたguidをグローバル一意と見なすことができる(同じidを2つ生成する場合は少ない).ググイドは先端で使うのが少ないようですが、現在はバックエンドインターフェースを要求するたびにこの方法を呼び出して、ググイドを生成して転送します.
  • 6.一ヶ月の日数を取得する
      function isLeapYear (year) {
        if (year % 100 === 0) {
          if (year % 400 === 0) {
            return true;
          }
        } else if (year % 4 === 0) {
          return true;
        }
        return false;
      }
      /**
       *           
       * @return {number}
       * @param {string | number}  year month
       * @example
       * getDaysInMonth(2017, 9)
       */
      function getDaysInMonth (year, month) {
        return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
      }
    
  • は1年と月に入ってきて、この月に戻って何日間がありますか?この中にもisLeaphYear方法が含まれています.閏年かどうか判断します.カレンダーまたは日付選択コンポーネントを実現する時に使うべきです.
  • までです.
    7.フィルタ対象の属性
      /**
       *              
       * @param{object, array} obj key
       * @return{object}
       * @example
       * pick(obj, [key1, key2])
       */
      function pick (obj, keys) {
        let result = {}
        if (!obj || !keys.forEach) {
          return result
        }
        keys.forEach((item) => {
          if (obj.hasOwnProperty(item)) {
            result[item] = obj[item]
          }
        })
        return result
      }
    
  • は1つのオブジェクトと1つの配列に入ってきて、配列を巡回して、入力されたオブジェクトが配列に含まれる属性がある場合、抽出され、フィルタで抽出された属性からなるオブジェクトを返します.
  • この方法は多くの用途があります.例えば、一つのインターフェースから結果の対象をもらいました.上の多くの属性はしばらく使えないかもしれません.この方法でフィルタリングできます.例えば、以前はvueでプロジェクトを書いていた時、インターフェースから戻ってきたオブジェクトをvueのdata属性としてページをレンダリングしていましたが、この時はこのオブジェクトはvueのインスタンスに動的に結び付けられています.しかし、一部の属性ページはまったく使えないので、これらの属性をモニターしてみなければなりません.このような時にインターフェースから戻ってきた相手をスクリーニングしてvueに与えたdataは合理的です.
  • 8.対象かどうかを判断する
      /**
       *                
       * @param{object} obj 
       * @return{object}
       * @example
       * isObject (null) isObject (() => {} )
       */
    function isObject (obj) {
        var type = typeof obj;
        return type === 'function' || type === 'object' && !!obj;
      }
    
  • は、着信パラメータが合法的なオブジェクトかどうかを判断し、functionタイプはtrueに戻り、nullはfalseに戻ります.
  • 9.一つの関数がnative codeかどうかを判断する
      /**
       *                   
       * @param{function} Ctor 
       * @return{boolean}
       * @example
       * isNative (window.Symbol)  isNative (window.Promise)
       */
    function isNative (Ctor) {
      return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
    }
    
  • javascript原生が持っている方法はtoStringを使って文字列に変換するときに、Math.max.toString()は「function max(){native code]」というフィールドを含みます.
  • この方法は、ある原生特性が現在のブラウザによってサポートされているかどうかを判断することができる.例えばisNative(window.Promise)はchromeの中でtrueに戻ります.chromeが元の生s 6文法をサポートしているので、ieの中に入れたらfalseに戻ります.
  • 10.深さクローンオブジェクト
      /**
       *                   
       * @param{object} obj 
       * @return{object}
       * @example
       * cloneDeep(obj)
       */
      function cloneDeep (obj) {
        if (!isObject(obj)) return obj;
        let result
        if (Array.isArray(obj)) {
          result = []
          obj.forEach((item) => {
            result.push(cloneDeep(item))
          })
          return result
        }
        result = {}
        for (let key in obj) {
          let item = obj[key]
          if (_.isObject(item)) {
            result[key] = cloneDeep(item)
          } else {
            result[key] = item
          }
        }
    
        return result
      }
    
  • は、まず、着信パラメータを判断し、正当なオブジェクトでない場合は、直接にその自身に戻る.属性を巡回して、属性に対象が含まれている場合は再度ConeDeepメソッドを再帰的に呼び出します.浅いクローンではObject.assignメソッドを直接使用できます.
  • 11.2つの場所の実際の距離を取得する
    /**
       *            ,     ,  ,       
       * @return {null|number}      ,      ,  null
       * @example
       * getDistance(31.282055633974, 121.379623888259)
       */
      function getDistance (endLat, endLon, startLat, startLon) {
        if (!startLat) {
          let address = Lizard.state.address
    
          if (address && address.lat) {
            startLat = address.lat
            startLon = address.lon
          }
        }
    
        //     
        if (!startLat) {
          return null
        }
    
        const PI = Math.PI
        let lon1 = (PI / 180) * startLon
        let lon2 = (PI / 180) * endLon 
        let lat1 = (PI / 180) * startLat  
        let lat2 = (PI / 180) * endLat 
        //       
        let R = 6378.137;  
    
        //       km,       ,  *1000      
        let d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * R;  
    
        return parseInt(d * 1000, 10)
      }
    
  • は、2つの点の経緯度を順次伝え、2つの点の距離を算出し、単位はkmである.この方法は実用的には少ないかもしれません.私はここに書いて、先端から距離を計算する方法としています.
  • 12.画像をロードする(promiseパッケージ)
    /**
       *     url,    promise  ,     resolve
       * @return {Promise} 
       * @example
       * loadImg(url).then(console.log('    ')).catch(err => {console.log(err)})
       */
      function loadImg (url) {
        return new Promise((resolve, reject) => {
          let img = new Image()
    
          img.addEventListener('load', function() {
            resolve([img.width, img.height])
          }, false)
    
          img.addEventListener('error', reject, false)
    
          img.src = url
        })
      }
    
  • この関数はECMAScript 6からの入門を参照して、promiseの古典的な応用例としてカウントされ、ロードが完了した後、promiseオブジェクトresoveは、画像の幅の高さに戻り、スタイルの調整などが行われます.ロードに失敗したらrejectに戻りますので、この方法を呼び出したらcatch方法で異常を捕捉する必要があります.
  • 13.文字列n回の繰り返し
    /**
       *      ,     ,       
       * @return {string} 
       * @param{string, number} str n 
       * @example
       * loadImg(url).then(console.log('    ')).catch(err => {console.log(err)})
       */
      const repeat = (str, n) => {
        let res = ''
        while (n) {
          if (n % 2 === 1) res += str
          if (n > 1) str += str
          n >>= 1
        }
        return res
      }
    
  • この関数はvueソースから見たのです.ビット演算子を使って、私に実現させると、すぐにn回の繰り返しを思い出すかもしれません.上の関数は実行時の時間の複雑さはほとんどn/2だけです.
  • 14.変数が'$'または'''''になるかどうか冒頭
    /**
       *      ,     '$'  '_'  
       * @return {Boolean} 
       * @param{string} str
       * @example
       * isReserved (‘$’)  isReserved (‘param’)
       */
    function isReserved (str) {
      var c = (str + '').charCodeAt(0);
      return c === 0x24 || c === 0x5F
    }
    
  • は同じvueのソースコードの中の方法で、変数が'$または''u'であるかどうかを判断します.最初に、charCodeAt(index)メソッドは文字列対応index位置の文字のUnicoodeコードを返します.'米ドル'に対応するUnicoodeコードは36です.ここで使っているのは16進数表記方法は0 x 24です.変数名がどの文字で始まるかを判断するには、上の方法を少し修正すればいいです.
  • ps:vueではどこでこの方法が使われていますか?行ってみました.vueのインスタンスを初期化したdataのオブジェクトを見た時に判断します.もしあなたのvueのインスタンスdataの中に'米ドル'または'_'と名付けられていたら.のオブジェクトは、この属性をget/setと再定義しません.簡単に言えば、vueのdataで$dataという属性を定義して、テンプレートに「{ドルdata}」をレンダリングすると、エラーが発生します.
  • 15.promise拡張-finally
    /**
       *    promise       finally,      ,    promise             
       * @param{function} callback
       * @example
       *  server.listen(0).then(function () { // run test }).finally(server.stop);
       */
    Promise.prototype.finally = function (callback) {
      let P = this.constructor;
      return this.then(
        value  => P.resolve(callback()).then(() => value).catch(e => {console.error(e)}),
        reason => P.resolve(callback()).then(() => { throw reason }).catch(e => {console.error(e)})
      );
    };
    
  • は、ECMAScript 6からの入門を参考にして、promiseオブジェクトの拡張方法の一つについては、前のpromise状態にかかわらず、いつもcalback関数を呼び出します.
  • 元コードに新たなcatchを追加しました.calback実行時にrejectのpromiseに対応した状態に戻りました.
  • 16.dom要素が現在のウィンドウ内にあるかどうかを判断する.
    /**
       *        dom              
       *         false   , true                true
       * @param {object,Boolean}
       * @example
       *  elementIsVisibleInViewport(document.querySelector('div'), true)
       */
    const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
      const { top, left, bottom, right } = el.getBoundingClientRect();
      const { innerHeight, innerWidth } = window;
      return partiallyVisible
        ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
            ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
        : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
    };
    
    おわりに
  • 再度追加