■前置き
JavaScriptにおけるevalとは非常に強力である反面、危険でもある(正しくパースされていないJSONなど)。またscriptの実行速度を低下させたりもする。そんな訳で以下のようなコードが世界には存在する。
■json.js
// JavaScript Document var json_parse = (function(){ //JSONをパースして、JavaScriptのデータ構造を生成する関数。 //これはシンプルな再帰下降パーサである //グローバル変数を生成することを避けるため、 //この関数は他の関数の中で定義される var at; var ch; var escapee = { '"' : '"', '\\': '\\', '/' : '/', b : 'b', f : 'f', n : 'n', r : 'r', t : 't' }; var text; var error = function(m){ throw{ name : 'SyntaxError', message: m, at : at, text : text }; }; var next = function(c){ if(c && c !== ch){ error("Expected '" + c + "' instead of '" + ch + "'"); } ch = text.charAt(at); at += 1; return ch; } var number = function(){ var number, string = ''; if(ch === '-'){ string = '-'; next('-'); } while(ch >= '0' && ch <= '9'){ string += ch; next(); } if(ch === '.'){ string += '.'; while(next() && ch >= '0' && ch <= '9'){ string += ch; } } if(ch === 'e' || ch === 'E'){ string += ch; next(); if(ch === '-' || ch === '+'){ string += ch; next(); } while(ch >= '0' && ch <= '9'){ string += ch; next(); } } number += string; if(isNaN(number)){ error("Bad number"); } else{ return number; } }; var string = function(){ var hex, i, string = ''; var uffff; if(ch === '"'){ while(next()){ if(ch === '"'){ next(); return string; } else if(ch === '\\'){ next(); if(ch === 'u'){ uffff = 0; for(i=0; i<4; i+=1){ hex = parseInt(next(), 16); if(!isFinite(hex)){ break; } uffff = uffff * 16 + hex; } string += String.fromCharCode(uffff); } else if(typeof escapee[ch] === 'string'){ string += escapee[ch]; } else{ break; } } else{ string += ch; } } } error("Bad string"); }; var white = function(){ while(ch && ch <= ' '){ next(); } }; var word = function(){ switch(ch){ case 't': next('t'); next('r'); next('u'); next('e'); return true; case 'f': next('f'); next('a'); next('l'); next('s'); next('e'); return false; case 'n': next('n'); next('u'); next('l'); next('l'); return null; } error("Unexpected '" + ch + "'"); }; var value; var array = function(){ var array = []; if(ch === '['){ next('['); white(); if(ch === ']'){ next(']'); return array; } while(ch){ array.push(value()); white(); if(ch === ']'){ next(']'); return array; } next(','); white(); } } error("Bad array"); }; var object = function(){ var key; var object = {}; if(ch === '{'){ next('{'); white(); if(ch === '}'){ next('}'); return object; } while(ch){ key = string(); white(); next(':'); object[key] = value(); white(); if(ch === '}'){ next('}'); return object; } next(','); white(); } } error("Bad object"); }; var value = function(){ white(); switch(ch){ case '{': return object(); case '[': return array(); case '"': return string(); case '-': return number(); default: return (ch >= '0' && ch <= '9')? number() : word(); } }; return function(source, reviver){ var result; text = source; at = 0; ch = ' '; result = value(); white(); if(ch){ error("Syntax error"); } return typeof reviver === 'function' ? function walk(holder, key){ var k; var v; var value = holder[key]; if(value && typeof value === 'object'){ for(k in value){ if(Object.hasOwnProperty.call(value, k)){ v = walk(value, k); if(v !== undefined){ value[k] = v; } else{ delete value[k]; } } } } return reviver.call(holder, key, value); }({'' : result}, '') : result; }; })();
■あとがき
出展「Douglas Crockford著『JavaScript: The Good Parts』(オライリー・ジャパン発行,2008)」
所用の為に本屋さんに言ったのですが、あまりに奥が深いので買った本です。JavaScriptを極めたいなら是非とも読んでみる事をお勧めします。