格式:JSON(JavaScript Object Notation缩写)是一种用于数据交换的文本格式,目的是取代繁琐笨重的 XML 格式。
复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。
字符串必须使用双引号表示,不能使用单引号。
对象的键名必须放在双引号里面。
数组或对象最后一个成员的后面,不能加逗号。
- ["one", "two", "three"]
- { "one": 1, "two": 2, "three": 3 }
- {"names": ["张三", "李四"]
- [ { "name": "张三"}, {"name": "李四"} ]
- { name: "张三", 'age': 32 } // 属性名必须使用双引号
-
- [32, 64, 128, 0xFFF] // 不能使用十六进制值
-
- { "name": "张三", "age": undefined } // 不能使用 undefined
-
- { "name": "张三",
- "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
- "getName": function () {
- return this.name;
- }
- } // 属性值不能使用函数和日期对象
JSON对象是 JavaScript 的原生对象,用来处理 JSON 格式数据。它有两个静态方法:JSON.stringify()和JSON.parse()。
JSON.stringfy()方法将一个值转为JSON字符串,该字符串符合JSON格式,且可被JSON.parse()还原
例:
- JSON.stringify('abc') // ""abc""
- JSON.stringify(1) // "1"
- JSON.stringify(false) // false
- JSON.stringify([]) // "[]"
- JSON.stringify({}) // "{}"
-
- JSON.stringify([1,"false",false])
- // '[1,"false",false]'
-
- JSON.stringfy({name:"张三"})
- // '{name:张三}'
-
- 上方将各种类型的值,转为JSON字符串,对于原始类型,转换结果会带双引号
- JSON.stringify('foo') === "foo" // false
- JSON.stringify('foo') === "\"foo\"" // true
- // 上面代码中,如果不是内层的双引号,将来还原的时候,引擎就无法知道原始值是布尔值还是字符串。
JSON.stringify()方法会忽略对象的不可遍历的属性
- var obj = {};
-
- Object.defineProperties(obj,{
- 'foo':{
- value:1,
- enumerable:true
- },
- 'bar':{
- value:2,
- enumerable:false
- }
- });
-
- JSON.stringify(obj); // "{"foo":1}"
-
- // bar是obj对象的不可遍历属性,JSON.stringify方法将会忽略这个属性
JSON.stringify()方法还可以接受一个数组,作为第二个参数,指定参数对象的哪些属性需要转为字符串
- var obj = {
- 'prop1':'value1',
- 'prop2':'value2',
- 'prop3':'value3'
- };
-
- var selectedProperties = ['prop1','prop2'];
-
- JSON.stringify(obj,selectedProperties)
- // "{"prop1":"value1","prop2":"value2"}"
- // JSON.stringify()方法的第二个参数指定,只转prop1和prop2的两个属性
类似白名单的数组,只对对象的属性有效,对数组无效。
- JSON.stringfy(['a','b'],[0]);
- // "["a","b"]"
-
- JSON.stringify({0:'a',1:'b'},['0']);
- // "{"0":"a"}"
第二个参数还可以是函数,用来更改JSON.stringify()的返回值
- function f(key,value) {
- if(typeof value === "number") {
- value = 2 * value;
- }
- return value;
- }
-
- JSON.stringify({a:1,b:2},f);
- // '{"a":2,"b":4}'
-
- // f函数,接受两个参数,分别是被转换的对象的键名和键值。键值为数值的话,将乘2,否则原样返回,
注意:这个处理函数是递归处理所有的键
- var obj = {a:{b:1}}
-
- function f(key.value) {
- console.log("[" + key + "]:" + value);
- return value;
- }
-
- JSON.stringify(obj.f);
- //[]:[object object]
- //[a]:[object object]
- //[b]:1
- //'{"a":{"b":1}}'
-
- // 对象 obj 一共会被函数 f 处理三次,输出的最后那行是JSON.stringify()的默认输出,第一次键名为空,键值是整个对象的obj;第二次键名为a,键值是{b:1};第三次键名为b,键值为1
递归处理中,每一次处理的对象,都是前一次返回的值
- var obj = {a:1};
-
- function f(key,value) {
- if (typeof value === 'object') {
- return {b:2};
- }
- return value * 2;
- }
-
- JSON.stringify(obj,f);
- // "{"b":4}"
-
- // 上面代码中,f函数修改了对象obj,接着JSON.stringify()方法就递归处理修改后的对象obj
如果处理函数返回undefined或没有返回值,则该属性会被忽略
- function f(key,value) {
- if (typeof(value) === "string") {
- return undefined;
- }
- return value;
- }
-
- JSON.stringify({a:"abc",b:123},f)
- // '{"b":123}'
-
- // a属性被处理后,返回undefined,于是该属性被忽略
JSON.stringify()还可以接受第三个参数,用于增加返回的JSON字符串的可读性
默认返回单行字符串,对于大型JSON对象,可读性差。第三个参数使得每个属性单独占据一行,并将每个属性前面添加指定的前缀(前缀不超过10个字符)
- // 默认输出
- JSON.stringify({p1:1,p2:2})
- // JSON.stringify({p1:1,p2:2})
-
- // 分行输出
- JSON.stringify({p1:1,p2:2},null,'\t')
- /*
- {
- "p1":1,
- "p2":2
- )
- */
-
- // 第三个属性\t在每个属性前面添加一个制表符(从当前位置移动到下一个tab位置),然后分行显示
第三个属性如果是数字,则表示在每个属性前面添加的空格(不超过10个)
- JSON.stringify({ p1: 1, p2: 2 }, null, 2);
- /*
- "{
- "p1": 1,
- "p2": 2
- }"
- */
JSON.parse()方法用于将 JSON 字符串转换成对应的值。
例1:
- JSON.parse('{}'); // {}
- JSON.parse('true'); // true
- JSON.parse('"foo"'); // "foo"
- JSON.parse('[1,5,"false"]'); // [1,5,"false"]
- JSON.parse('null'); // null
-
- var o = JSON.parse('{"name":"张三"}');
- o.name // 张三
例2:传入字符串不是有效的JSON格式,将报错
- JSON.parse("'String'");
- // 报错
-
- // 双引号字符串中是一个单引号字符串,因为单引号字符串不符合JSON格式,所以报错
try...catch代码块,解析错误
- try {
- JSON.parse("'String'");
- }catch(e) {
- console.log('parsing error');
- }
JSON.parse()方法接受一个处理函数,作为第二个参数,用法与JSON.stringify()方法类似
- function f(key,value) {
- if (key === 'a') {
- return value + 10;
- }
- return value;
- }
-
- JSON.parse('{"a":1,"b":2}',f);
- // {a:11,b:2}
-
- // JSON.parse()的第二个参数是一个函数,如果键名是a,该函数会将键值加上10
js中有三种声明函数的方法
function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面
- function print(s) {
- console.log(s);
- }
-
- // 代码中命名了一个print函数,使用print()这种形式,就可以调用相应的代码,这叫做函数的声明
funciton命令声明函数,还可采用变量赋值的写法
- var print = function(s) {
- console.log(s);
- }
-
- // 将一个匿名函数赋值给变量,匿名函数又被称为函数表达式,赋值语句右侧只能放表达式
采用函数表达式声明函数时,function命令后面不带有函数名。加上函数名,则函数名只在函数体内部有效,在函数体外部无效
- var print = funciton x() {
- coonsole.log(typeof x);
- };
-
- print();
- // funciton
-
- // 上面代码在函数表达式中,加入了函数x。x只在函数体内部可用,指代函数表达式本身,其他地方都不可用
- // 两种用法:
- //(1)函数体内部调用自身
- //(2)方便除错(除错工具显示函数调用栈时,显示函数名,而不再显示这里是一个匿名函数)
var f = funciton f() {};
函数表达式末尾加分号,表示语句结束;而函数声明在结尾的大括号后面不用加分号。
- var add = new Function(
- 'x',
- 'y',
- 'return x + y'
- );
-
- // 等同于
- function add(x,y) {
- return x + y;
- }
-
- // Function构造函数接受三个参数,除了最后一个参数是add函数的“函数体”,其他参数都是add函数的参数
可传递任意数量参数给Function构造函数,仅最后一个参数会被当做函数体;若仅一个参数,该参数就是函数体
- var foo = new Function(
- 'return "hello world";'
- );
-
- // 等同于
- function foo() {
- return "hello world";
- }
-
- // function构造函数可不使用new命令,返回结果相同。(声明函数的方式不直观,无人使用)