[转]json2.js 源码解读
生活随笔
收集整理的這篇文章主要介紹了
[转]json2.js 源码解读
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這一部分是對Date String Number Boolean擴展toString方法,Date的toString是返回UTC格式的字符串,而后面幾個是返回原始值。
function f(n) {// 返回兩位數字字符串return n < 10 ? ‘0‘ + n: n;}if (typeof Date.prototype.toJSON !== ‘function‘) {//如果Date不支持原生的toJSON方法Date.prototype.toJSON = function() {//擴展Date的toJSON方法//是否是有窮數,如果為true,返回根據UTC時間計算出的年月日時分秒 YYYY-MM-DDThh:mm:ssZ如果為false,返回nullreturn isFinite(this.valueOf()) ? this.getUTCFullYear() + ‘-‘ + f(this.getUTCMonth() + 1) + ‘-‘ + f(this.getUTCDate()) +‘T‘ + f(this.getUTCHours()) + ‘:‘ + f(this.getUTCMinutes()) + ‘:‘ + f(this.getUTCSeconds()) + ‘Z‘: null;};//擴展String Number Boolean的toJSON方法String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function() {return this.valueOf();//返回他們的原始值};}這里是擴展Stringify方法
function str(key, holder) {//第一次調用時 key:‘‘, holder:{‘‘: value} var i, // The loop counter.k, // The member key.v, // The member value.length, mind = gap,//初始mind和gap都為""partial, value = holder[key];//第二次調用時 value就是傳入的鍵所對應的值//如果value有toJSON方法if (value && typeof value === ‘object‘ && typeof value.toJSON === ‘function‘) {value = value.toJSON(key);//調用value.toJSON方法}if (typeof rep === ‘function‘) {//如果replace是一個方法value = rep.call(holder, key, value);}// 判斷value類型switch (typeof value) {case ‘string‘://如果是字符串,加引號return quote(value);case ‘number‘://如果是數值//有窮數用原生的String()將數值轉為符串,否則返回nullreturn isFinite(value) ? String(value) : ‘null‘;case ‘boolean‘://如果是bool值或者null,返回String(value)case ‘null‘:return String(value);case ‘object‘://如果是對象if (!value) {//nullreturn ‘null‘;}gap += indent;//分隔符partial = [];//臨時數組if (Object.prototype.toString.apply(value) === ‘[object Array]‘) {//數組length = value.length;for (i = 0; i < length; i += 1) {//對數組的每一項遞歸調用strpartial[i] = str(i, value) || ‘null‘;}// 如果partial為[],返回"[]"// 如果 gap分隔符存在,返回[\n‘ + gap + partial.join(‘,\n‘ + gap) + ‘\n‘ + mind + ‘]‘// 如果分隔符不存在,返回‘[‘ + partial.join(‘,‘) + ‘]‘v = partial.length === 0 ? ‘[]‘: gap ? ‘[\n‘ + gap + partial.join(‘,\n‘ + gap) + ‘\n‘ + mind + ‘]‘: ‘[‘ + partial.join(‘,‘) + ‘]‘;gap = mind;//重置為""return v;}if (rep && typeof rep === ‘object‘) {//如果rep存在且為數組或者對象length = rep.length;//如果是數組for (i = 0; i < length; i += 1) {//過濾if (typeof rep[i] === ‘string‘) {k = rep[i];//鍵是數組的值v = str(k, value);//遞歸調用if (v) {//"key": value 或者"key":valuepartial.push(quote(k) + (gap ? ‘: ‘: ‘:‘) + v);}}}} else {//如果不是數組或方法或不存在for (k in value) {if (Object.prototype.hasOwnProperty.call(value, k)) {v = str(k, value);if (v) {partial.push(quote(k) + (gap ? ‘: ‘: ‘:‘) + v);}}}}v = partial.length === 0 ? ‘{}‘: gap ? ‘{\n‘ + gap + partial.join(‘,\n‘ + gap) + ‘\n‘ + mind + ‘}‘: ‘{‘ + partial.join(‘,‘) + ‘}‘;gap = mind;return v;}}下面是圖解:
這里是擴展parse方法
if (typeof JSON.parse !== ‘function‘) {//如果JSON沒有parse方法cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;JSON.parse = function(text, reviver) {//擴展JSON方法var j;function walk(holder, key) {// walk({‘‘:j},‘‘)var k, v, value = holder[key];//value第一次是傳入的eval編譯后的結果if (value && typeof value === ‘object‘) {//如果value存在并且是對象for (k in value) {if (Object.prototype.hasOwnProperty.call(value, k)) {//是否有原型上的屬性v = walk(value, k);//遞歸調用獲取結果if (v !== undefined) {value[k] = v;} else {delete value[k];}}}}//調用walk之前有判斷,所以在這里reviver肯定存在return reviver.call(holder, key, value);}text = String(text);cx.lastIndex = 0;if (cx.test(text)) {text = text.replace(cx,function(a) {// \u0600 ---> \\u0600 因為\需要轉義return ‘\\u‘ + (‘0000‘ + a.charCodeAt(0).toString(16)).slice( - 4);});}// text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, ‘@‘) // =>把\\t \\uffff 這類轉為@// =>var text=‘{"a":"\\t44","b":"\\uffff"}‘; text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, ‘@‘); //{"a":"@44","b":"@"}// replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ‘]‘)// =>把非空字符串、數值、bool、null替換為]// .replace(/(?:^|:|,)(?:\s*\[)+/g, ‘‘)// => 把 [ ,[ :[ 這類的替換為‘‘// 如果剩余的字符串只剩下 ]:,{}和空格 就是測試通過,否則拋出異常if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, ‘@‘) .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ‘]‘).replace(/(?:^|:|,)(?:\s*\[)+/g, ‘‘))) {j = eval(‘(‘ + text + ‘)‘);//eval()傳入的參數加括號編譯return typeof reviver === ‘function‘ ? walk({//如果第二個參數是函數 返回walk({‘‘:j},‘‘)的結果,否則直接返回eval編譯的結果‘‘: j},‘‘) : j;}throw new SyntaxError(‘JSON.parse‘);};}通過一系列的替換操作,如果剩下的字符串只剩下 ]:,{}和空格,測試通過,接下來就可以用eval編譯。
如果parse方法的第二個參數存在,返回walk的調用結果,否則直接返回eval編譯結果。
//reviver的用法: // var jsontext = ‘{ "hiredate": "2008-01-01T12:00:00Z", "birthdate": "2008-12-25T12:00:00Z" }‘; // var dates = JSON.parse(jsontext, dateReviver); // console.log(dates); // function dateReviver(key, value) { // var a; // if (typeof value === ‘string‘) { // a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); // if (a) { // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], // +a[5], +a[6])); // } // } // return value; // }; 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的[转]json2.js 源码解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTTPS 证书配置
- 下一篇: POJ 1651 Multiplicat