日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转]json2.js 源码解读

發布時間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转]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;}}

下面是圖解:

function quote(string) {//將傳入的字符串加上引號,有必要轉義的先轉義escapable.lastIndex = 0;//起始位置從0開始return escapable.test(string) ? ‘"‘ + string.replace(escapable,function(a) {//匹配到的字符 如\t \nvar c = meta[a];//字符對應的轉義表示//如果c是字符串 ,直接返回對象中鍵所對應的值 ‘\t‘=>‘\\t‘//如果c不是字符串,也就是說它不在meta對象中,這時做不同的轉義處理://拿 a為"\u0600"舉例//a.charCodeAt(0) =>1536//a.charCodeAt(0).toString(16) => 600//(‘0000‘ + a.charCodeAt(0).toString(16)) =>0000600//(‘0000‘ + a.charCodeAt(0).toString(16)).slice( - 4) 取最后四位 => 0600//‘\\u‘ + (‘0000‘ + a.charCodeAt(0).toString(16)).slice( - 4)) ‘\\u0600‘return typeof c === ‘string‘ ? c: ‘\\u‘ + (‘0000‘ + a.charCodeAt(0).toString(16)).slice( - 4);}) + ‘"‘: ‘"‘ + string + ‘"‘;}

這里是擴展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 源码解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。