JSON.parser() 是JSON 格式的一个函数, 它用于将object 数据类型转换成为JSON 数据类型, 这里我们来自己实现一下JSON.parser() 函数.
JSON 格式中, 可以将需要处理数据类型分为以下6类, 注意这里的意思是需要处理的属性类型有以下6 类, 表示的是数据处理的6 种情况;
真实的数据分类并不是按以下分类的, 这里需要注意.
自己实现一个函数, 用于判断两个对象是否相等, 实现代码如下:
// 判断两个对象是否相等的函数
const objectEquals = (a, b) => {
    // 如果 a, b相等,则返回 true,否则返回 false
    // Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
    // 换句话来说 Object.getOwnPropertyNames()方法返回的是对象所有 key 组成的数组 list
    var aProps = Object.getOwnPropertyNames(a)
    var bProps = Object.getOwnPropertyNames(b)
    if (aProps.length != bProps.length) {
        return false
    }
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i]
        if (typeof a[propName] === ‘object‘) {
            let judge = objectEquals(a[propName], b[propName])
            if (!judge) {
                return false
            }
        } else if (a[propName] !== b[propName]) {
            return false
        }
    }
    return true
}
这里匹配的字符串主要是括号的匹配, 理解下面的代码
// 返回对象 ‘{‘ 对应的 ‘}‘,返回数组 ‘[‘ 对应的 ‘]‘
const getAimIndex = (string, index) => {
    let str = string
    // breakStr是结束判断字符
    let startStr = str[index]
    let breakStr = startStr === ‘{‘ ? ‘}‘ : ‘]‘
    let judgeNum = 0
    /*
    判断逻辑:
        1. 遍历从 i = 1 开始
        2. if temp = ‘{‘ || ‘[‘, judgeNum++
        3. if temp = ‘}‘ || ‘]‘, judgeNum--
        4. if temp = ‘}‘ || ‘]‘ && judgeNum === 1, return i
     */
    for (let i = index, len = str.length; i < len; i++) {
        let temp = str[i]
        if (temp === startStr) {
            judgeNum++
        } else if (temp === breakStr && judgeNum !== 1) {
            judgeNum--
        } else if (temp === breakStr && judgeNum === 1) {
            return i
        }
    }
    // log(‘judgeNum: ‘, judgeNum)
}
let str = ‘{{{}}}‘
console.log(getAimIndex(str, 0))
这个实现过程中, 很多内容的实现都需要递归去完成, 因此对于递归有基本的了解会比较好理解.
理解过程可能不会很费劲, 但是如果自己实现的话, 个人认为如果能够将 Title2.2 判断对象是否相等 独立实现就可以自己实现JSON.parse()
在生产tokens 数组中, 直观上, 我们会认为我们只需要将JSON 中有意义的字符串添加在tokens 数组中即可, 但是, 这样做会存在一个问题:
对于如下代码
{
    "obj1": true,
    "obj2": "true"
}
上面代码中, obj1 obj2 属性本质上是不一样的, 一个是String 类型, 一个是Boolean 类型, 而我们从JSON 中读取的内容类型均为String 类型; 因此为了确保完美解析JSON 数据, 我们必须在tokens 数组中存储JSON 数据的值类型
同时, 由于我们生成对象的时候必须依赖值的类型, 值本身去生成对象, 因此需要提供一个方法返回值内容
综上所述, 我们使用面向对象的思想来解决这个问题:
const log = console.log.bind(console)
const TYPE = {
    "[object Number]": 1,
    "[object String]": 2,
    "[object Null]": 3,
    "[object Boolean]": 4,
    "character": 5,
    "escapeCharater": 6
}
const includeEscapeCharacter = function(str) {
    let asciiEscape = [0, 39, 34, 92, 10, 13, 11, 9, 8, 12]
    for (let i = 0, len = str.length; i < len; i++) {
        let temp = str[i].charCodeAt(0)
        if (asciiEscape.indexOf(temp) !== -1) {
            return true
        }
    }
    return false
}
const dealEscape = (str) => {
    let escape = {
        b: `\b`,
        f: ‘\f‘,
        n: ‘\n‘,
        r: ‘\r‘,
        t: ‘\t‘,
        ‘\\‘: ‘\\‘,
        ‘\/‘: ‘\/‘,
        ‘\"‘: ‘\"‘,
        "\‘": "\‘"
    }
    let result = ‘‘
    let string = str
    let i = 0
    let len = string.length
    // log(str)
    while (i < len) {
        let temp = string[i]
        if (temp === ‘\\‘) {
            let endIndex = i + 1
            result += escape[string[endIndex]]
            i = endIndex + 1
        } else {
            result += temp
            i++
        }
    }
    return result
}
const getType = function (value) {
    if (value === ‘:‘ || value === ‘{‘ || value === ‘}‘ || value === ‘[‘ || value === ‘]‘) {
        return 5
    }
    if (includeEscapeCharacter(value)) {
        return 6
    }
    let type = Object.prototype.toString.apply(value)
    return TYPE[type]
}
class JsonValue {
    constructor(value) {
        this.value = String(value)
        this.type = getType(value)
    }
    toString() {
        if (this.type === 1) {
            return Number(this.value)
        } else if (this.type === 2) {
            return String(this.value)
        } else if (this.type === 3) {
            return null
        } else if (this.type === 4) {
            return this.value === ‘true‘
        } else if (this.type === 5) {
            return String(this.value)
        } else if (this.type === 6) {
            return dealEscape(this.value)
        }
    }
}
const __main = () => {
    let a = new JsonValue(‘a‘)
    let b = new JsonValue(1)
    log(a)
    log(a.toString())
    log(b)
    log(b.toString())
}
__main()
tokens 数组中存储的都是JsonValue 类型的数据;
接下来遍历JSON 数据添加内容即可
这个过程就是遍历tokens 数组, 依照符号(:)的索引index, tokens[index - 1] 为key, tokens[index + 1] 为value; 找到key-value 对, 然后添加到结果即可; 需要注意的是这个过程需要考虑Object 的嵌套, 以及Array中Object 的嵌套, 这里需要使用递归去处理
这个过程的核心代码如下: 根据不同的情况, 处理不同的内容
// 获取key-value对的value值
const getTokensValue = (index, array) => {
    let judge = array[index].value
    if (judge === ‘{‘) {
        let nextIndex = getAimIndex(array, index)
        let sliceList = array.slice(index + 1, nextIndex)
        return parsedDict(sliceList)
    } else if (judge === ‘[‘) {
        let nextIndex = getAimIndex(array, index)
        let sliceList = array.slice(index + 1, nextIndex)
        return conversionObj(sliceList)
    } else {
        return array[index].toString()
    }
}
代码地址: JSON.parse() 的实现
原文:https://www.cnblogs.com/oulae/p/12749375.html