最新更新时间:2020年08月06日22:51:48

本文内容:
数据的序列化,是指将非String类型的数据转化为String类型的数据;
数据的反序列化,是指将序列化后的String类型的数据转化为序列化前的类型的数据;

JavaScript数据类型的识别方法及限制
  • 四种方法:typeof || instanceof || constructor || Object.prototype.toString
//typeof 判断基本数据类型
//能够识别基本数据类型 Null会被识别成object
//不能识别具体的引用类型 Function除外
console.log(typeof 1);//number
console.log(typeof '');//string
console.log(typeof true);//boolean
console.log(typeof undefined);//undefined
console.log(typeof function(){});//function
console.log(typeof null);//object
console.log(typeof new Date());//object
console.log(typeof /[a-z]/);//object
console.log(typeof []);//object
console.log(typeof {});//object
console.log('----------------');
//instanceof 判断左边是否是右边的实例对象 所有的对象都是Object的实例
//能够识别内置对象类型(引用数据类型) 自定义类型及其父类型
//不能识别标准类型(基本数据类型) 返回false
//不能识别undefined和null 会报错
console.log(1 instanceof Number);//false
console.log('' instanceof String);//false
console.log(true instanceof Boolean);//false
// console.log(undefined instanceof undefined);//报错
console.log(function(){} instanceof Function);//true
// console.log(null instanceof null);//报错
console.log(new Date() instanceof Date);//true
console.log(/[a-z]/ instanceof RegExp);//true
console.log([] instanceof Array);//true
console.log([] instanceof Object);//true
console.log(function(){} instanceof Object);//true
console.log({} instanceof Object);//true
console.log('----------------');
//constructor 获取构造函数
//能够识别标准类型(基本数据类型)、内置对象类型(引用数据类型)、自定义类型
//不能识别undefined、null会报错,因为它们没有构造函数
console.log((1).constructor);//function Number() { [native code] }
console.log(('').constructor);//function String() { [native code] }
console.log(true.constructor);//function Boolean() { [native code] }
// console.log(undefined.constructor);//报错
console.log((function(){}).constructor);//function Function() { [native code] }
// console.log(null.constructor);//报错
console.log((new Date()).constructor);//function Date() { [native code] }
console.log(/[a-z]/.constructor);//function RegExp() { [native code] }
console.log([].constructor);//function Array() { [native code] }
console.log({}.constructor);//function Object() { [native code] }
console.log('----------------');
//Object.prototype.toString 对象类属性 获取目标对象类型
//能够识别标准类型(基本数据类型)和内置对象类型(引用数据类型) 不能识别自定义类型
console.log(Object.prototype.toString.call(1));//[object Number]
console.log(Object.prototype.toString.call(''));//[object String]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(function () {}));//[object Function]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call(new Date()));//[object Date]
console.log(Object.prototype.toString.call(/[a-z]/));//[object RegExp]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call({}));//[object Object]
Boolean
let a = true;
//序列化
let serializationA = JSON.stringify(a);
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(typeof serializationA);//string
console.log(typeof deserializationA);//boolean
Number
let a = 1;
//序列化
let serializationA = JSON.stringify(a);
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(typeof serializationA);//string
console.log(typeof deserializationA);//number
Undefined
  • undefined类型无法进行反序列号

报错:Uncaught SyntaxError: Unexpected token u in JSON at position 0

let a = undefined;
//序列化
let serializationA = JSON.stringify(a);
console.log(typeof serializationA);//undefined
//反序列化 报错
let deserializationA = JSON.parse(serializationA);// 报错
Null
let a = null;
//序列化
let serializationA = JSON.stringify(a);
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(typeof serializationA);//string
console.log(typeof deserializationA);//object
Regexp
  • 正则表达式会被转化为空对象
let a = /[a-z]/ig;
//序列化
let serializationA = JSON.stringify(a);
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(serializationA);//{}
console.log(deserializationA);//{}
Array
let a = [1,2,3];
//序列化
let serializationA = JSON.stringify(a);
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(typeof serializationA);//string
console.log(deserializationA instanceof Array);//true
Object
  • 场景一:对象没有嵌套,使用 JSON.stringify 和 JSON.parse 进行序列化和反序列化;
  • 对象中的值如果是函数,会直接丢失kv对;对象中的值如果是正则表达式,会将正则表达式转化为空对象;
let a = {
    a: 1,
    b: 'wan',
    c: '',
    d: null,
    e: undefined,
    f: true,
    g: function(){console.log('g')},
    h: /d+$]/ig,
    j: [1, 2, 3]
};
//序列化
let serializationA = JSON.stringify(a);
console.log(serializationA);//{"a":1,"b":"wan","c":"","d":null,"f":true,"h":{},"j":[1,2,3]}
//反序列化
let deserializationA = JSON.parse(serializationA);
console.log(deserializationA);//{ a: 1, b: 'wan', c: '', d: null, f: true, h: {}, j: [ 1, 2, 3 ] }
  • 场景二:对象没有嵌套,兼容函数和正则表达式的方案,但是丢失数据类型,在进行反序列化的过程中也只是一种伪方法;
let a = {
    a: 1,
    b: 'wan',
    c: '',
    d: null,
    e: undefined,
    f: true,
    g: function(){},
    h: /d+$/ig,
    j: [1, 2, 3]
};
//序列化
function serialization(a){
    var res = [];
    for (let key in obj) {
        if(obj[key] === ''){
            res.push(key + ':' + '""')
        }else if(Array.isArray(obj[key])){
            res.push(key + ':[' + obj[key] + ']')
        }else{
            res.push(key + ':' + obj[key])
        }
    }
    return res.join('|')
}
let seri = serialization(obj)
console.log(seri);;// a:1|b:wan|c:""|d:null|e:undefined|f:true|g:function(){}|h:/d+$]/gi|j:[1,2,3]
//反序列化
function deserialization(str){
    let res = {};
    str.split('|').forEach((item)=>{
        let kv = item.split(':')
        if(kv[1] === 'null'){
            kv[1] = null
        }else if(kv[1] === 'undefined'){
            kv[1] = undefined
        }else if(kv[1] === '""'){
            kv[1] = ''
        }else if(kv[1] === 'true'){
            kv[1] = true
        }else if(kv[1] === 'false'){
            kv[1] = false
        }else if(kv[1].indexOf('function') > -1 || kv[1].indexOf('[') > -1 || kv[1].indexOf('/') > -1){
            kv[1] = eval('(' + kv[1] + ')')
        }
        res[kv[0]] = kv[1]
    })
    return res
}
let deseri = deserialization(seri);
console.log(deseri);//{ a: '1', b: 'wan', c: '', d: null, e: undefined, f: true, g: function(){}, h: /d+$]/gi, j: [ 1, 2, 3 ] }
  • 场景三:对象嵌套,丢失数据类型,在进行反序列化的过程中也只是一种伪方法;
let a = {
    a: 1,
    b: 'wan',
    c: '',
    d: null,
    e: undefined,
    f: true,
    g: function(){},
    h: /d+$/ig,
    j: [1, 2, 3],
    k: [1, 2, [3]],
    m: [1, 2, {m1:1}, function(){}],
    n:{n1:1, n2:function(){}, n3:/[a-z]/ig, n4:[4,5,6], n5:{n51:1}}
};
//序列化
function serialization(obj){
    function arr2arr(arr){
        let res = '['
        arr.forEach((item)=>{
            if(Object.prototype.toString.call(item) === '[object Object]'){
                res += '{' + serialization(item) + '},'
            }else if(Object.prototype.toString.call(item) === '[object Array]'){
                res += arr2arr(item) + ']'
            }else{
                res += item + ','
            }
        })
        res = res.slice(0,res.length-1)
        return res + ']'
    }
    var res = [];
    for (let key in obj) {
        if(obj[key] === ''){
            res.push(key + ':' + '""')
        }else if(Object.prototype.toString.call(obj[key]) === '[object Object]'){
            res.push(key + ':{' + serialization(obj[key]) + '}');
        }else if(Object.prototype.toString.call(obj[key]) === '[object Array]'){
            let temp = arr2arr(obj[key])
            res.push(key + ':' + temp);
        }else{
            res.push(key+':'+obj[key]);
        }
    }
    return res
}
var seri = serialization(a).join('|');//a:1|b:wan|c:""|d:null|e:undefined|f:true|g:function(){}|h:/d+$/gi|j:[1,2,3]|k:[1,2,[3]]|m:[1,2,{m1:1},function(){}]|n:{n1:1,n2:function(){},n3:/[a-z]/gi,n4:[4,5,6],n5:{n51:1}}
//反序列化
function deserialization(str){
    let res = {};
    let regArr = /^\[.*\]$/ig;//以[开始 匹配任何包含零个或多个单个字符(除了换行和行结束符) 以]结尾
    let regObj = /^\{.*\}$/ig;
    str.split('|').forEach((item)=>{
        //重置正则表达式的lastIndex属性
        regArr.lastIndex = -1
        regObj.lastIndex = -1
        // let kv = item.split(':')
        let kv = [item.slice(0,item.indexOf(':')), item.slice(item.indexOf(':')+1)]
        if(kv[1] === 'null'){
            kv[1] = null
        }else if(kv[1] === 'undefined'){
            kv[1] = undefined
        }else if(kv[1] === '""'){
            kv[1] = ''
        }else if(kv[1] === 'true'){
            kv[1] = true
        }else if(kv[1] === 'false'){
            kv[1] = false
        }else if(regArr.test(kv[1]) || regObj.test(kv[1])){
            kv[1] = eval('(' + kv[1] + ')')
        }
        res[kv[0]] = kv[1]
    })
    return res
}
let deseri = deserialization(seri);//{ a: '1',b: 'wan',c: '',d: null,e: undefined,f: true,g: 'function(){}',h: '/d+$/gi',j: [ 1, 2, 3 ],k: [ 1, 2, [ 3 ] ],m: [ 1, 2, { m1: 1 }, [Function] ],n:{ n1: 1,n2: [Function: n2],n3: /[a-z]/gi,n4: [ 4, 5, 6 ],n5: { n51: 1 } } }
同一个正则表达式第二次匹配不到的解决方案
  • 异常场景
let str = '[1,2,3]'
let reg = /^\[.*\]$/ig;
console.log(reg.test(str));//true
console.log(reg.test(str));//false
  • 解决方案一:取消正则表达式修饰符g,不执行全局匹配

g 修饰符用于执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)

let str = '[1,2,3]'
let reg = /^\[.*\]$/i;
console.log(reg.test(str));//true
console.log(reg.test(str));//true
  • 解决方案二:重置正则表达式的lastIndex属性为0或者-1
let str = '[1,2,3]'
let reg = /^\[.*\]$/i;
console.log(reg.test(str));//true
reg.lastIndex = -1;
console.log(reg.test(str));//true
  • 引申:正则表达式的贪婪模式懒惰模式

贪婪模式,表示最大长度匹配字符串,比如,n+匹配任何包含至少一个 n 的字符串、n*匹配任何包含零个或多个 n 的字符串
懒惰模式,表示最小长度匹配字符串,比如,n?匹配任何包含零个或一个 n 的字符串

参考资料

感谢阅读,欢迎评论^-^