JSON.stringify中replacer参数的简单介绍

2020-03-06

介绍

JSON全称是JavaScript Object Notation,就是说呢JSON啊,是一种用来表示JavaScript语言中的对象的方式,尤其是,它定义了,一个对象,如果它所有的成员都是可序列化的并且是可反序列化的(可转化为字符串并可由字符串创建),那么这个对象该如何用字符串来表示,并且这个对象转成字符串之后,再用同样的运算的逆运算转回来,得到的对象还是一样的.

举个例子,可以在浏览器验证

let a = [1,2,3,true,'hello'];
let testString = '[1,2,3,true,"hello"]';
testString === JSON.stringify(a);
// true

let aFromJSONString = JSON.parse(testString);
aFromJSONString;
// [1, 2, 3, true, "hello"] (可以看到和a是一样的)

for (let i in a) {
    console.log(a[i] == aFromJSONString[i]);
}
// 可以看到两个数组的每个元素都是相等的

let x = {tom: 1000, mike: 2000, andy: 3000};
JSON.parse(JSON.stringify(x));
// {tom: 1000, mike: 2000, andy: 3000} (是相等的)

概括起来就是说JSON规定了如何将一个JavaScript对象序列化用于应用程序之间的数据交换,以及当该序列到达目的之后,如何再反序列回来得到原来的对象,就是这么简单,这里呢,『数据交换』,通俗的讲就是数据通过媒介传输,可以指同一个端点内部的应用程序间的数据交换,也可以只相隔千里的两个应用程序通过互联网实现的数据交换,甚至,比如说,一台ARM架构的手机上运行着的JavaScript应用程序的对象,通过JSON,也能传输给另一台PC机上运行的应用程序,后者接收到序列之后,对之进行反序列化,得到的对象和原来的对象在JavaScript中,语意上,绝对是一致的.

JSON就介绍到这里.

JSON.stringify中的replacer

我在翻看JSON.stringify的函数声明时,看到的是

/**
* Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
* @param value A JavaScript value, usually an object or array, to be converted.
* @param replacer A function that transforms the results.
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;

什么意思呢,就是说,replacer是一个函数,它的一个参数,假设它叫做text,那么这个text必须是一个string,它还有一个参数,假设它叫做replacer,这个replacer啊是一个函数,什么样的函数呢?这个叫做replacer的函数它接受一个,假设它叫做key,的string类型的参数,和一个,假设它叫做value,任何类型的参.一句话概括,就是stringify接受一个或两个参数(replacer后面的问号表示它是可选的),一个string类型的,和一个函数,这个函数接受一个key和一个value作为参数,输出不确定类型的值.

这就是JSON.stringify的函数签名.

可是前面我们看到要在对象和JSON字符串之间转来转去,不是只要JSON.stringify(对象转JSON)和JSON.parse(JSON转对象)就够了吗?当然,是够了,所以这个replacer参数是可选的,你可以看到它后面加了个问号,现在让我们来看一下它怎么用,先举个例子:

let transformer = (key, value) => {
    if (value % 2 == 1) {
        return 0;
    }
    else {
        return value
    }
}

let array = [1, 2, 3, 4, 5];

JSON.stringify(array, transformer);

// "[0,2,0,4,0]"

可以看到我们定义的transformer函数被分别用于检验输入对象的每一个成员和每一个成员对应的值,这里我们定义transformer用于:1)判断对象的一个成员的值是否是奇数,如果是,将其置0,如果不是奇数,则原样返回,这个transformer函数即作为JSON.stringify函数的replacer参数的实参,起到的作用的根据对象的成员的值的条件返回不同的值.

再举一个例子:

let salary = {tom: 1000, mike: 2000, andy: 3000};

let adder = (key, value) => {
    if (key === 'tom') {
        return value * 1.5;
    }
    else {
        return value;
    }
};

JSON.stringify(salary, adder)
// "{"tom":1500,"mike":2000,"andy":3000}"

这里我们定义了名为adder的函数作为JSON.stringify函数的replacer参数的实参,它用于检查对象的成员名称是否满足某些条件,例如这里它判断,如果成员名叫tom,那么返回的对应的值就乘以1.5,起到了按照成员名称条件返回的效果.

再看一下嵌套对象的情形

let x = {
    a: 1,
    b: "abc",
    c: {
        d: 234,
        e: 12,
        f: "def"
    }
}

let tester = (key, value) => {
    if ((typeof value) === 'number') {
        return value * 10;
    }
    else {
        return value;
    }
});

JSON.stringify(x, tester);
// "{"a":10,"b":"abc","c":{"d":2340,"e":120,"f":"def"}}"

let anotherTester = (key, value) => {
    console.log(value);
    if ((typeof value) === 'number') {
        return value * 10;
    }
    else {
        return value;
    }
};

JSON.stringify(x, anotherTester);

// {a: 1, b: "abc", c: {…}}
// 1
// abc
// {d: 234, e: 12, f: "def"}
// 234
// 12
// def
// "{"a":10,"b":"abc","c":{"d":2340,"e":120,"f":"def"}}"

其中x是一个嵌套对象,由于嵌套其中的也是一个基本对象,所以也是可JSON化的(基本对象本身也是基本对象),定义的判断函数tester同样也能递归地检查嵌套对象的键和值,而判断器形式上,不加修改地和刚才两个例子是类似的,然后我们修改了判断器,它打印出检查的顺序,先是整个对象,然后是成员的值.

总结

JSON是一种将JavaScript中的对象(当然现今也能被实现于其他对象)转化为字符串,以及将字符串转化为合法的JavaScript对象的一套转换规则,JSON.stringfy函数将对象转化问字符串,JSON.parse函数再将字符串转化回原来的对象,JSON只对基本类型和基本对象组成的对象(也属于基本对象)有定义,具体是:数字(包括浮点型),字符串,布尔值,数值(其成员也是基本对象),Object(基本对象),函数也是对象,并能作为参数和返回值在调用语句和返回值之间进行传递,JSON.stringify的第二个参数(其实也和JSON.parse的第二个参数效果一样的)起到根据对象的成员和成员对应的值的具体情况,动态地替换相应的成员的值的作用.

参考文献

[1] JSON.parse() - JavaScript | MDN

[2] JSON

[3] JSON - Wikipedia

经验交流javascript

介绍Google LightHouse

我的网站的加载速度还是比较快的