phi

I'm a Game Programmer and Frontend Engineer passionate about programming education. Math / C / C++ / C# / JavaScript / HTML5 / CSS3 / Python

phiaryjust a creator

JavaScript で, 華麗に URL パラメーターを取得してオブジェクトに変換する方法

9 years ago

昨日, JavaScriptでURLパラメーターを取得し配列に格納しておく - Qiita というエントリーがバズってて, 自分も似たような機能をよく自作するので紹介したいと思います.

タイトルはちょっと盛っちゃってますが, 見る人によっては 気持の良い実装コードになっていると思います.

Code

QueryString というオブジェクトに対して, parse, stringify をそれぞれ定義しています.

var QueryString = {  
  parse: function(text, sep, eq, isDecode) {
    text = text || location.search.substr(1);
    sep = sep || '&';
    eq = eq || '=';
    var decode = (isDecode) ? decodeURIComponent : function(a) { return a; };
    return text.split(sep).reduce(function(obj, v) {
      var pair = v.split(eq);
      obj[pair[0]] = decode(pair[1]);
      return obj;
    }, {});
  },
  stringify: function(value, sep, eq, isEncode) {
    sep = sep || '&';
    eq = eq || '=';
    var encode = (isEncode) ? encodeURIComponent : function(a) { return a; };
    return Object.keys(value).map(function(key) {
      return key + eq + encode(value[key]);
    }).join(sep);
  },
};

parse の方は, reduce の第二引数にオブジェクトを渡すってとこが肝ですね.

isDecodeisEncode は, false のとき空関数が呼ばれるので無駄にオーバーヘッドかかっちゃいますが, ループ内で何度も判定するのはナンセンスだし, if ~ else で分岐して同じようなコードを書くのも微妙だなと思い, コードの美しさを優先した次第です.

QueryString.parse

解説です. コード中にコメント書きまくってます.

  parse: function(text, sep, eq, isDecode) {
    // デフォルト値を設定
    text = text || location.search.substr(1); // 省略時は URL パラメータ
    sep = sep || '&'; // 省略時は &
    eq = eq || '=';   // 省略時は =
    // デコードするかどうか
    var decode = (isDecode) ? decodeURIComponent : function(a) { return a; };
    // sep(&) で split した配列を reduce で回した結果を返す
    return text.split(sep).reduce(function(obj, v) {
      // eq(=) で split して一番目を key 二番目を value として obj に代入
      var pair = v.split(eq);
      obj[pair[0]] = decode(pair[1]);
      return obj;
    }, {});
  },

Examples

普通に使う

QueryString.parse('hoge=100&foo=bar'); // {"hoge":"100", "foo":"bar"}  

引数省略時は location.search.substr(1) がパース対象となる

// http://hoge.com?foo=100&bar=bon だった場合
QueryString.parse(); // {"foo":"100", "bar":"bon"}  

& と = 以外の文字も指定できる(第2と第3引数)

QueryString.parse('2*4|4*2', '|', '*'); // {"2":"4","4":"2"}  

decode するかどうかも指定可能(第4引数)

QueryString.parse('名前=%E3%83%95%E3%82%A1%E3%82%A4', null, null, true); // {"名前":"ファイ"}  

QueryString.stringify を実装しよう

解説です. parse と同じくコード中にコメント書きまくってます.

  stringify: function(value, sep, eq, isEncode) {
    // デフォルト値を設定
    sep = sep || '&'; // 省略時は &
    eq = eq || '=';   // 省略時は =
    // エンコードするかどうか
    var encode = (isEncode) ? encodeURIComponent : function(a) { return a; };
    // Object.keys で key 配列を取得し, それを map で回した結果を sep(&) で join して返す
    return Object.keys(value).map(function(key) {
      // key, value を eq(=) で連結した文字列を返す
      return key + eq + encode(value[key]);
    }).join(sep);
  },

Examples

普通に使う

QueryString.stringify({"hoge":"100", "foo":"bar"})  

& と = 以外の文字も指定できる(第2と第3引数)

QueryString.stringify({"2":"4","4":"2"}, '|', '*'); // 2*4|4*2  

encode するかどうかも指定可能(第4引数)

QueryString.stringify({"名前":"ファイ"}, null, null, true); // 名前=%E3%83%95%E3%82%A1%E3%82%A4  

Demo

上記で紹介した実装と実例の実行サンプルです. 実際にイジって遊んでみてください♪