美文网首页饥人谷技术博客
JS数组以及JSON知识

JS数组以及JSON知识

作者: 海山城 | 来源:发表于2017-08-30 16:17 被阅读0次

    1.JSON 格式的数据需要遵循什么规则

    JSON格式是一种用于数据交换的文本格式,它对值的类型和格式有严格的规定

    • 复合类型的值只能是数组或者对象(包括空数组和空对象都是合格的 JSON 值),不能是函数,正则表达式对象,日期对象
    • 简单类型的值只有4种:字符串,数值(必须以十进制表示),布尔值和null(不能为NaN,+Infinity(正无穷), -Infinity(负无穷)和undefined)
    • 字符串必须用双引号,不能用单引号
    • 对象的键名必须放在双引号里面
    • 数组或对象最后一个成员的后面,不能加逗号

    以下是合格的 JSON 值。

    ["one", "two", "three"]
    { "one": 1, "two": 2, "three": 3 }
    {"names": ["张三", "李四"] }
    [ { "name": "张三"}, {"name": "李四"} ]
    

    以下是不合格的 JSON 值。

    { 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;
      }
    } // 不能使用函数和日期对象
    

    注:JavaScript 对象和 JSON 的关系
    JSON 格式数据参考于 JS 对象字面量的语法,二者属于不同的范畴。JavaScript 对象中很多类型(函数、正则、Date) JSON 格式的规范并不支持,JavaScript 对象的字面量写法更宽松。

    2.使用 JSON 对象实现一个简单的深拷贝函数(deepCopy)

    先上代码:

    var oldObject = {name:"小明",
                     age:25,
                     sex:"男",
                     city:"南京",
                     wife:{name:"小牛", sex:"女", age:24, city:"北京"},
                     friends:["小红", "小白", "小黄"]
                     }
    var jsonString = JSON.stringify(oldObject)
    var newObject = JSON.parse(jsonString )
    console.log(newObject.wife.sex)                        //女
    console.log(newObject.wife == oldObject.wife)          //false
    console.log(newObject.friends == oldObject.friends)    //false,两个false说明newObject的子对象开辟新的堆内存,和oldObject的子对象的堆内存不一样了  
    

    原理:
    先用JSON.stringify()将对象,转化成JSON形式的字符串;然后在通过JSON.parse()将JSON字符串解析成一个新的对象。

    JSON.stringify()
    JSON.stringify方法用于将一个值转为字符串。该字符串符合 JSON 格式,并且可以被JSON.parse方法还原
    使用方式以及注意点:
    1.各种类型的值转换成JSON 字符串

    JSON.stringify('abc') // ""abc"" ---->原始类型的字符串,转换结果会带双引号。这是因为将来还原的时候,双引号可以让 JavaScript 引擎知道,abc是一个字符串,而不是一个变量名
    JSON.stringify(1) // "1"
    JSON.stringify(false) // "false"
    JSON.stringify([]) // "[]"
    JSON.stringify({}) // "{}"
    
    JSON.stringify([1, "false", false])
    // '[1,"false",false]'
    
    JSON.stringify({ name: "张三" })
    // '{"name":"张三"}'
    

    2.需要注意的是对象和数组的内部的一些奇怪的值的转换(不主动设置toJSON方法的情况)
    对象:

    var obj = {
      a: function(){},                                 //函数-->被JSON.stringify过滤
      b: new Date('Fri, 26 Aug 2011 07:13:10 GMT'),    //日期对象-->调用日期对象内部的toJSON转换成了"2011-08-26T07:13:10.000Z"形式的字符串
      c: undefined,                                    //undefined-->被JSON.stringify过滤
      d: "undefined",                                  //"undefined"字符串-->"undefined"字符串
      e: -Infinity,                                    //-Infinity-->null
      f: NaN,                                          //NaN-->null
      g: null,                                         //null-->null
      h: {},                                           //{}-->{},空对象仍然转换成空对象
      i: [],                                           //[]-->[],空数组仍然转换成空数组
      j: /foo/,   //正则表达式                          //正则表达式-->{},即空对象
      k: "normal"                                      //"normal"字符串-->"normal"字符串
    };
    
    JSON.stringify(obj)
     //结果 "{"b":"2011-08-26T07:13:10.000Z","d":"undefined","e":null,"f":null,"g":null,"h":{},"i":[],"j":{},"k":"normal"}"
    

    数组:通过JSON.stringify转换后,函数和undefined都被转换成了null,其他的转换结果和对象的一样

    var obj2 = [function(){}, new Date('Fri, 26 Aug 2011 07:13:10 GMT'), undefined, -Infinity, NaN, null, {}, [],  /foo/, "normal" ]
    
    JSON.stringify(obj2)
     //结果 "[null,"2011-08-26T07:13:10.000Z",null,null,null,null,{},[],{},"normal"]"
    

    3.JSON.stringify方法会忽略对象的不可遍历属性。(enumerable: false;也叫不可枚举属性)

    var obj = {};
    Object.defineProperties(obj, {
      'foo': {
        value: 1,
        enumerable: true
      },
      'bar': {
        value: 2,
        enumerable: false
      }
    });
    
    JSON.stringify(obj);
     // 结果 "{"foo":1}"
    

    JSON.parse()
    JSON.parse方法用于将JSON字符串转化成对象。如下:

    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 // 张三
    

    如果传入的字符串不是有效的JSON格式,JSON.parse方法将报错。

    JSON.parse("'String'") // illegal single quotes
    // SyntaxError: Unexpected token ILLEGAL
    //双引号字符串中是一个单引号字符串,因为单引号字符串不符合JSON格式,所以报错
    

    总结:用JSON方法进行深拷贝,对象或者数组中不能有,函数,undefined等通过JSON.stringify()转换后发生变化的东西,所以这种方法进行深拷贝具有局限性

    3.数组方法里push、pop、shift、unshift、join、splice分别是什么作用?用 splice函数分别实现push、pop、shift、unshift方法

    push:在数组最后添加一个元素,数组长度发生变化

    var arr = [3, 4, 5, 6]
    arr.push('hello')
    console.log(arr)         // [3, 4, 5, 6, 'hello']
    

    pop:把数组最后一位弹出来,返回,数组长度发生变化

    var value = arr.pop()
    console.log(value)       // 'hello'
    console.log(arr)         //[3, 4, 5, 6]
    

    unshift:在数组最前面添加一个元素,数组长度发生变化

    var arr = [3, 4, 5, 6]
    arr.unshift('hello')
    console.log(arr)         // ['hello', 3, 4, 5, 6 ]
    

    shift:把数组最前面一位弹出来,返回,数组长度发生变化

    var value = arr.shift()
    console.log(value)       // 'hello'
    console.log(arr)         // [3, 4, 5, 6 ]
    

    join(separator): 把数组中的所有元素转换一个字符串。separator是指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符。

    var arr = [3, 4, 5, 6]
    var str = arr.join('-')
    console.log(str)        // "3-4-5-6"
    

    splice:用于一次性解决数组添加、删除(这两种方法一结合就可以达到替换效果),但是只能处理数组中连续的多少个值的增删改。这方法有三个参数:
    1.开始索引
    2.删除元素的个数
    3.插入的新元素,当然也可以写多个
    splice方法返回一个由删除元素组成的新数组,没有删除则返回空数组

    //删除2,3
    var oldArray = new Array(1,2,3,4,5);
    var newArray = oldArray.splice(1,2)
    console.log(newArray)   // [2, 3]
    console.log(oldArray)   // [1, 4, 5]
    
    //在3,4之间添加6,7,8
    var oldArray = new Array(1,2,3,4,5);
    var newArray = oldArray.splice(3,0,6,7,8)  // 插入是从第一个参数指定的下标前面开始插的
    console.log(newArray)   // [] ,因为删除了0个元素,所以为空数组
    console.log(oldArray)   // [1, 2, 3, 6, 7, 8, 4, 5]
    
    //替换,原理就是先删后增,将2,3,4换成6,7,8
    var oldArray = new Array(1,2,3,4,5);
    var newArray = oldArray.splice(1,3,6,7,8) 
    console.log(newArray)   // [2,3,4] 
    console.log(oldArray)   // [1, 6, 7, 8, 5]
    
    //用 splice函数分别实现push、pop、shift、unshift方法
    //push,末尾添加hello
    var s = "hello"
    var oldArray = [3, 4, 5, 6]
    oldArray .splice(oldArray .length, 0, s)
    console.log(oldArray )  //[3, 4, 5, 6, "hello"]
    //pop,末尾删除hello
    var newArray = oldArray .splice(oldArray .length-1, 1)
    console.log(newArray)  // ["hello"]
    console.log(oldArray )  //[3, 4, 5, 6]
    //unshift,开头添加world
    var s = "world"
    var oldArray = [3, 4, 5, 6]
    oldArray .splice(0, 0, s)
    console.log(oldArray )  //[ "world", 3, 4, 5, 6]
    //shift,开头删除world
    var newArray = oldArray .splice(0, 1)
    console.log(newArray)  // ["world"]
    console.log(oldArray )  //[3, 4, 5, 6]
    

    4.写一个函数,操作数组,数组中的每一项变为原来的平方,在原数组上操作

    function squareArr(arr){
      for(var i = 0; i < arr.length; i++){
        arr[i] = arr[i]*arr[i]
      }
    }
    var arr = [2, 4, 6]
    squareArr(arr)
    console.log(arr) // [4, 16, 36]
    

    5.写一个函数,操作数组,返回一个新数组,新数组中只包含正数

    function filterPositive(arr){
      for(var i = arr.length-1; i >= 0; i--){
        if(arr[i] <= 0 || (typeof arr[i] !== "number")){
          arr.splice(i, 1)
        }
      }
    }
    var arr = [3, -1,  2,  '饥人谷', true]
    filterPositive(arr)
    console.log(arr) //[3,  2]
    

    或者

    function filterPositive(arr){
      for(var i = 0; i < arr.length; i++){
        if((arr[i] <= 0) || (typeof arr[i] !== "number")){
          arr.splice(i, 1)
          i--
        }
      }
    }
    var arr = [3, -1,  2,  '饥人谷', true]
    filterPositive(arr)
    console.log(arr) //[3,  2]
    

    参考
    阮一峰 JavaScript 标准参考教程(alpha)

    相关文章

      网友评论

        本文标题:JS数组以及JSON知识

        本文链接:https://www.haomeiwen.com/subject/xluzdxtx.html