Javascript基础

基础语法

  1. 语句最好以分号; 结尾,以免自动补全时出错
  2. 严格区分大小写
  3. 变量、常量可以单独作为一个语句
  4. 变量名由字母、数字、下划线、$符合组成,且不能以数字开头
  5. 动态类型语言
  6. typeof 变量 返回函数类型,该结果本身为字符串

注释

// Comment
/* Block Comment
   块注释 */

数据类型

Number
  1. 不区分整数、浮点数,支持科学计数法(如1.2e3)
  2. 特殊值:NaN、Infinity
  3. 可直接做四则运算
字符串
  1. 用单引号或双引号括起来, 通过 \ 转义

    • 十六进制数:'\x##'表示,如'\x41'表示A
    • Unicode字符:\u#### 表示
  2. ES6新增多行字符串,通过反引号 `` 括起来

  3. 字符串拼接用 + 号,自动将非字符串转为字符串。ES6中新增模板字符串,反引号字符串中用${变量}代替变量

    var name = '小明';
    var age = 20;
    var message = `你好, ${name}, 你今年${age}岁了!`;
    alert(message);
    
  4. 常见字符串操作

    var s= 'Hello, world'
    
    s.length; // 13
    s[0]; // 'H'
    s[13]; // undefined 超出范围的索引不会报错,但一律返回undefined
    s[0] = 'X'; // 赋值不报错,但不会有任何效果
    
    s.indexOf('world'); // 返回7
    s.indexOf('World'); // 没有找到指定的子串,返回-1
    
    s.toUpperCase();
    s.toLowerCase();
    
    s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello'
    s.substring(7); // 从索引7开始到结束,返回'world'
    
布尔值
  1. true/false
  2. 与运算&&、或运算||
    • || 返回第一个对应为 true 的值,常用于返回备选组中第一个定义了且非空的值
    • && 返回第一个对应为 false 的值
    • !! 将变量转为 boolean 类型,如 !!'abc'
  3. 比较运算符:> < >= <= === ! 。建议用===做相等比较(不会自动转换类型);==会自动进行类型转换,可能得到奇怪的结果
  4. 浮点数比较有误差,可采用类似Math.abs( a - b ) < 0.000001比较
  5. 条件判断语句中把nullundefined0NaN和空字符串''视为false,其他值一概视为true
  6. NaN和谁对比都是false,包括自己
特殊值
  1. null空值,不同于0或''
  2. undefinednull 差别不大,仅在判断函数参数是否传递的情况下有用
数组
  1. 推荐:通过方括号[]定义,可包含任意类型,如[1, 2, 3.14, 'Hello', null, true];

  2. 通过Array定义,如 new Array(1,2,3.14)

  3. 通过序号索引 0 ~ length-1

  4. 数组操作

    arr.length; //返回字符串长度,可以赋值,不够补undefined,但不建议
    arr[1] = '99'; // 赋值
    arr.indexOf('30');// 搜索一个指定的元素的位置, 找不到返回-1
    
    arr.slice(0,3); //返回[0,3)位置的子数组副本
    arr.slice(3); //从索引3到结束
    arr.slice(); // 返回整个数组副本,用于复制数组
    
    arr.push('A', 'B'); // 往数组末尾添加任意元素,返回新长度
    arr.unshift('A', 'B');  // 往数组前添加任意元素,返回新长度
    arr.pop(); // 删除数组末尾元素,返回删除元素
    arr.shift(); // 删除数组头部元素,返回删除元素
    
    arr.sort(); //直接对当前元素排序,无返回值
    
    arr.reverse(); // 数组逆序,无返回值
    
    arr.splice(2, 3, 'a', 'b'); // 从指定的 索引2 开始删除 3个 元素,然后再从该位置添加若干元素'a' 'b',返回删除的元素;删除0个时相当于插入
    
    arr.concat(1, 'a', array2); // 组合任意元素和数组,并自动拆开数组,返回新的数组副本,不修改原数组
    
    arr.join('-'); // 将元素转为字符串后用连接符连接,返回结果字符串
    
  5. map / reduce / filter / sort

    • map 接收一个函数 f,逐个遍历数组元素,将函数 f 应用到每个元素。传入的参数共3个,分别为数组元素、元素索引、数组本身;但形参中函数 f 可以只有一个参数
    • reduce 接收一个函数 f,将函数结果和数组下一个元素做累计计算,比如 [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
    • filter 接收一个函数 f,若 f 返回true则保留,否则丢弃该元素。返回筛选后的新数组。
    • sort 可以接收一个函数 f(x,y),返回值1代表 x>y, 0 代表 x==y, -1代表 x<y .
      • 不接收函数的sort()会先将元素转成字符串再比较,则数字排序是按字典序排列,反直觉
      • sort()会直接修改原数组
    // map
    function pow(x) {
        return x * x;
    }
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
    console.log(results);
    
    // reduce
    var arr = [1, 3, 5, 7, 9];
    arr.reduce(function (x, y) {
        return x + y;
    }); // 25
    
    // filter
    var r,
        arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
    r = arr.filter(function (element, index, self) {
        return self.indexOf(element) === index;
    }); // 筛掉重复元素
    
    var arr = [10, 20, 1, 2];
    arr.sort(function (x, y) {
        if (x < y) {
            return -1;
        }
        if (x > y) {
            return 1;
        }
        return 0;
    });
    console.log(arr); // [1, 2, 10, 20], 若直接sort()则为1, 10, 2, 20
    
  6. 其余高阶函数

    • every(f)方法可以判断数组的所有元素是否满足测试条件,均满足时返回true
    • find(f)方法用于查找符合条件的第一个元素,如果找到了,返回这个元素,否则,返回undefined 。类似于filter,但仅返回第一个元素
    • findIndex(f)find(f)类似,也是查找符合条件的第一个元素,不同之处在于findIndex(f)会返回这个元素的索引,如果没有找到,返回-1
    • forEach(f)map(f)类似,它也把每个元素依次作用于传入的函数,但不会返回新的数组。forEach()常用于遍历数组,因此,传入的函数不需要返回值
对象(map)
  1. 键(属性)为字符串类型,值可为任意数据类型

  2. 通过对象变量名.属性名 获取值(建议);也可采用['xxx'] 的形式,特别是当属性名包含特殊字符时,需用 '' 括起来,此时只能用[]访问

  3. 新增、删除属性

    var xiaoming = {
        name: '小明'
    };
    xiaoming.age; // undefined
    delete xiaoming.age; // 删除一个不存在的school属性也不会报错
    xiaoming.age = 18; // 新增一个age属性
    xiaoming.age; // 18
    delete xiaoming.age; // 删除age属性
    
  4. 检验是否包含某个属性

    'name' in xiaoming; // true
    'toString' in xiaoming; // true, 从父类继承
    xiaoming.hasOwnProperty('toString'); // false, 检验自身非继承属性
    

变量定义

  1. 需通过var定义,仅作用在函数内部
  2. 若省略var,且未使用'use strict'; 或浏览器不支持strict模式,则为全局变量,会与html中其他js文件共用变量。使用'use strict'后,会将其限制在函数内部

流程控制

  1. 条件判断 if () { ... } else { ... }

  2. 循环语句

    • for(初始条件; 判断条件; 迭代语句)

    • for...in... 遍历属性(针对对象和数组)

      // 遍历对象
      var o = {
          name: 'Jack',
          age: 20,
          city: 'Beijing'
      };
      
      for (var key in o) {
          console.log(key); // 'name', 'age', 'city'  
          
          if (o.hasOwnProperty(key)) { // 过滤对象继承属性
              console.log(key); // 'name', 'age', 'city'
          }
      }
      // 遍历数组
      var a = ['A', 'B', 'C'];
      for (var i in a) {
          console.log(i); // '0', '1', '2'  字符串类型索引
          console.log(a[i]); // 'A', 'B', 'C'
      }
      
  3. while (...) {}

  4. do {} while(...);

Map和Set

  1. ES6开始支持

  2. Map支持非字符串的键,通过成员方法访问

    var m = new Map(); // 定义空Map
    var m = new Map([[1, 'a'], ['b', 2]]); // 通过二维数组定义
    m.set('t', 3);
    m.get('t'); // 3
    m.delete('t'); // true
    m.has('t'); // false
    
  3. Set对key自动去重

    var s = new Set();
    var s = new Set([1, 2, 3, 3, '3']);  // 通过一维数组定义
    s.add(4);
    s.delete(4);
    s.has(1); // true
    

Iterable

  1. ES6开始支持,Array、Set、Map均为iterable类型

  2. 支持 for ... of 循环,只会循环集合本身元素; 而 for ... in 遍历的实际上是对象属性名称

    var a = ['A', 'B', 'C'];
    a.name = 'Hello';
    
    for (var x in a) {
        console.log(x); // '0', '1', '2', 'name'
    }
    
    for (var x of a) {
        console.log(x); // 'A', 'B', 'C'
    }
    
  3. 更好的循环方式是 forEach (ES 5.1开始支持) ,入参为函数

    var s = new Set(['A', 'B', 'C']);
    s.forEach(function (element, sameElement, set) {
        console.log(element);
    });
    
    var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
    m.forEach(function (value, key, map) { // 注意入参顺序
        console.log(value);
    });
    
    // 如果对某些参数不感兴趣,由于JavaScript的函数调用不要求参数必须一致,因此可以忽略它们。例如,只需要获得Array的element
    a.forEach(function(element)) { 
        // 可以添加第二参数为索引index,第三参数为类型array
        console.log(element) // 'A', 'B', 'C'
    }
    

函数

  1. 定义

    // 函数定义
    function abs(x) {
        if (x >= 0) {
            return x;
        } else {
            return -x;
        }
    }
    // 通过匿名函数定义
    var abs = function (x) {...}; // 注意末尾分号
    
  2. 若没有返回值,返回 undefined

  3. 函数调用时,入参可大于定义数,此时多余参数为undefined ;可少于定义数,此时函数中未赋值对应参数接收到undefined

  4. arguments ,只在函数内部起作用,获得调用者传入的所有参数,类似于Array。如包含length属性,常用于判断入参个数

  5. rest参数,获取多余参数(ES6新标准)

    function foo(a, b, ...rest) {
        console.log('a = ' + a);
        console.log('b = ' + b);
        console.log(rest);
    }
    
    foo(1, 2, 3, 4, 5);
    // 结果:
    // a = 1
    // b = 2
    // Array [ 3, 4, 5 ]
    
  6. 注意return语句,由于JavaScript自动在行末补分号 ; ,所以不要在此次直接换行

    function foo() {
        return  // 返回undefined
            { name: 'foo' };
    }
    

变量作用域

  1. 声明在函数内部的变量,只在函数体内起作用

  2. 嵌套函数,内部可以访问外部函数变量(支持覆盖);但外部不能访问内部。搜索时内部函数由内向外搜索变量。

  3. 变量提升:JavaScript会将所有变量声明提升至函数顶部,但不提升赋值。故规范做法是在函数顶部用一个 var 定义好所有变量

    function foo() {
        var x = 'Hello, ' + y;  // 返回 Hello, undefined
        console.log(x);
        var y = 'Bob';
    }
    // 定义方式举例:
    var
        t,
        a = 0,
        b = 1,
        arr = [0, 1];
    
  4. 全局作用域:不定义在任何函数内部的变量。实际上全局变量绑定在唯一全局变量—— window变量上,key和value分别为变量名和值。alert也是window的变量之一

  5. 名字空间:不同Js文件使用相同的全局变量或同名顶层函数,将导致冲突。推荐做法是将自己的所有变量和函数绑定到一个全局变量中

    // 唯一的全局变量MYAPP:
    var MYAPP = {};
    
    // 其他变量:
    MYAPP.name = 'myapp';
    MYAPP.version = 1.0;
    
    // 其他函数:
    MYAPP.foo = function () {
        return 'foo';
    };
    
  6. 块级作用域: ES6中引入 let 关键字,定义的变量仅作用于函数块内,如for语句内

  7. 常量:ES6中引入 const 关键字,同样具有块级作用域

解构赋值(ES6)

  1. 同时对一组变量赋值

    // 数组用方括号
    var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
    let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']]; // 支持嵌套,但结构需一致
    
    // 对象用花括号,取出若干属性
    var person = {
        name: '小明',
        age: 20,
        gender: 'male',
        passport: 'G-12345678',
        school: 'No.4 middle school',
        address: {
            city: 'Beijing',
            street: 'No.1 Road',
            zipcode: '100001'
        }
    };
    // 可嵌套,但层次需一致。address只用于说明层次,未定义
    var {name, address: {city:location, zip, province="Beijing"}} = person; // 可用等号定义默认值,用冒号定义与属性不同名的变量
    name; // '小明'
    location; // 'Beijing'
    zip; // undefined, 因为属性名是zipcode而不是zip
    province; // 'Beijing',而不是undefined
    address; // Uncaught ReferenceError: address is not defined
    
    var x, y;
    ({x, y} = { name: '小明', x: 100, y: 200}); // 对于已定义变量,可能需要加括号,否则报错
    
    // 变量交换
    [x, y] = [y, x]
    
    // 函数用对象作为参数
    function buildDate({year, month, day, hour=0, minute=0, second=0}) {
        return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
    }
    
    buildDate({ year: 2017, month: 1, day: 1 });
    

方法

  1. 将函数赋值给属性

    var xiaoming = {
        name: '小明',
        birth: 1990,
        age: function () {
            var y = new Date().getFullYear();
            return y - this.birth;
        }
    };
    
    xiaoming.age; // function xiaoming.age()
    xiaoming.age(); // 今年调用是25,明年调用就变成26了
    
  2. 注意this指向,不支持嵌套(嵌套时在内部函数还原为 windownull )。嵌套时应在外层先用其他变量接收,如定义一个 var that=this ,内部再调用that

  3. 若函数在外部声明,必须用obj.xxx()的形式调用,此时this正确;如直接调用外部函数,则this指向全局变量window(非strict)或为 null(strict模式)

  4. 使用apply控制this指向,第一参数为需绑定this的变量,第二个为Array,为函数参数。直接调用外部函数,第一参数用null。call类似,除了第二参数不用Array,直接按顺序传入多个参数。

    function getAge() {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
    
    var xiaoming = {
        name: '小明',
        birth: 1990,
        age: getAge
    };
    
    xiaoming.age(); // 25
    getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
    
  5. 装饰器:比如替换内置函数

    /* 计算parseInt调用次数 */
    'use strict';
    
    var count = 0;
    var oldParseInt = parseInt; // 保存原函数
    
    window.parseInt = function () {
        count += 1;
        return oldParseInt.apply(null, arguments); // 调用原函数
    };
    

闭包

  1. 含义:将函数 f2 作为函数 f1 返回值,同时该内部函数 f2 可以引用外部 f1 的参数和局部变量,并保存在返回的函数 f2. 函数 f2 称为闭包。

  2. 闭包引用的局部变量不被回收,同时在 f2 被调用时才会被赋值。所以应避免引用循环遍变量,或者后续会发生变化的变量。或者再创建一个函数,将该函数参数绑定循环变量当前值

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i;
        });
    }
    return arr;
} // 调用数组中的三个函数,返回值均为16

function count() { // 引用循环变量的正确做法
        var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i));
    }
    return arr;
}
  1. 可以用于将多参函数变单参函数

    function make_pow(n) {
        return function (x) {
            return Math.pow(x, n);
        }
    }
    
  2. 封装私有变量

    'use strict';
    
    function create_counter(initial) {
        var x = initial || 0;
        return {
            inc: function () {
                x += 1;
                return x;
            }
        }
    }
    
    var c1 = create_counter();
    c1.inc(); // 1
    c1.inc(); // 2
    c1.inc(); // 3
    
    var c2 = create_counter(10);
    c2.inc(); // 11
    c2.inc(); // 12
    c2.inc(); // 13
    

箭头函数

  1. ES6标准引入的新函数定义方式

    // 单语句
    var fn = x => x * x;
    
    // 多参数,多语句
    (x, y, ...rest) => {
        var i, sum = x + y; 
        for (i=0; i<rest.length; i++) {
            sum += rest[i];
        }
        return sum;
    }
    
    // 与{...}函数体语法冲突,直接返回对象需加括号
    x => ({ foo: x })
    
  2. 箭头函数中修复了 this 指向,使其总是指向词法作用域,也就是外层调用者 obj ,不需要再用 var that = this 保留外层this。但箭头函数中的this本质上继承于外侧的function,故需放置在function内部,不能作为独立的成员函数。此外apply和call的第一个参数将被忽略

    var obj = {
        birth: 1990,
        getAge: function (year) {
            var b = this.birth; // 1990
            var fn = () => year - this.birth; // this指向obj对象
            return fn.call({birth:2000}, year); //this.birth仍为1990
        }
    };
    obj.getAge(2015); // 25
    
  3. 注意事项

生成器generator

  1. 与函数类似,但是使用 function* 定义

  2. 调用next(),每次运行到 yield 关键字处输出value和done(true表示generator已结束)。直到return结束

  3. 调用方式

    • generator赋值给一个变量后,使用 next() 获取一个元素
    • 使用 for...of,自动判断generator是否结束
    function* fib(max) {
        var
            t,
            a = 0,
            b = 1,
            n = 0;
        while (n < max) {
            yield a;
            [a, b] = [b, a + b];
            n ++;
        }
        return;
    }
    
    for (var x of fib(10)) {
        console.log(x); // 依次输出0, 1, 1, 2, 3, ...
    }
    

包装对象

  1. 强烈建议不要使用

  2. null的类型是objectArray的类型也是object ,用typeof无法区分出nullArray和通常意义上的object—— {}

  3. 包装对象用new创建:

    var n = new Number(123); // 123,生成了新的包装类型
    var b = new Boolean(true); // true,生成了新的包装类型
    var s = new String('str'); // 'str',生成了新的包装类型
    
  4. 如果省略了 new 关键字, Number()BooleanString()被当做普通函数,把任何类型的数据转换为numberbooleanstring类型(注意不是其包装类型)

    var b2 = Boolean('false'); // true! 'false'字符串转换结果为true!因为它是非空字符串!
    
  5. 基本规则

    • 不要使用new Number()new Boolean()new String()创建包装对象;
    • parseInt()parseFloat()来转换任意类型到number
    • String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
    • 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...}
    • typeof操作符可以判断出numberbooleanstringfunctionundefined
    • 判断Array要使用Array.isArray(arr)
    • 判断null请使用myVar === null
    • 判断某个全局变量是否存在用typeof window.myVar === 'undefined'
    • 函数内部判断某个变量是否存在用typeof myVar === 'undefined'
  6. number调用 toString() 需先将整数转成浮点数,或带括号

    123..toString(); // '123', 注意是两个点,代表不带小数部分的浮点数
    (123).toString(); // '123'
    

常见对象

  1. Date

    • 常见用法

      var now = new Date(); 
      now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
      now.getFullYear(); // 2015, 年份
      now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
      now.getDate(); // 24, 表示24号
      now.getDay(); // 3, 表示星期三
      now.getHours(); // 19, 24小时制
      now.getMinutes(); // 49, 分钟
      now.getSeconds(); // 22, 秒
      now.getMilliseconds(); // 875, 毫秒数
      now.getTime(); // 1435146562875, 以number形式表示的时间戳
      
      // Date对象创建方法一
      var d = new Date(2015, 5, 19, 20, 15, 30, 123);
      d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)
      // Date对象创建方法二(ISO 8601格式)
      var d = Date.parse('2015-06-24T19:49:22.875+08:00');
      d; // 1435146562875
      var d = new Date(1435146562875);
      d; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
      d.getMonth(); // 5
      
    • JavaScript的Date对象月份值从0开始,牢记0=1月,1=2月,2=3月,……,11=12月

    • 使用Date.parse()时传入的字符串使用实际月份0112,转换为Date对象后getMonth()获取的月份值为011

    • 转换到所在时区:先转为时间戳(表示从1970年1月1日零时整的GMT时区开始的那一刻,到现在的毫秒数)

      var d;
      if (Date.now) {
          t = Date.now(); // 老版本IE没有now()方法
      } else {
          t = new Date().getTime();
      } // t=1435146562875
      var d = new Date(t); // Date对象表示的时间总是按浏览器所在时区显示的
      
      d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关
      d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时
      
  2. RegExp 正则表达式

    • 定义方式

      var re1 = /ABC\-001/; // 使用两个斜杠 '/./'
      var re2 = new RegExp('ABC\\-001');  //因为字符串的转义问题,字符串的两个\\实际上是一个\
      
      re1; // /ABC\-001/
      re2; // /ABC\-001/
      
    • 判断是否匹配

      var re = /^\d{3}\-\d{3,8}$/;
      re.test('010-12345'); // true
      re.test('010-1234x'); // false
      re.test('010 12345'); // false
      
    • 切分字符串

      'a b   c'.split(' '); // ['a', 'b', '', '', 'c'] // 空格划分
      'a b   c'.split(/\s+/); // 正则,['a', 'b', 'c']
      
    • 分组

      var re = /^(\d{3})-(\d{3,8})$/;
      re.exec('010-12345'); // ['010-12345', '010', '12345'] 分别为整个字符串,匹配到的子串
      re.exec('010 12345'); // null 失败返回null
      
    • 非贪婪匹配(加 ?

      var re = /^(\d+?)(0*)$/;
      re.exec('102300'); // ['102300', '1023', '00']
      // 若不加?,贪婪匹配结果为['102300', '102300', '']
      
    • 全局搜索

      • 全局匹配可以多次执行exec()方法来搜索一个匹配的字符串
      • 当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引
      • 全局匹配类似搜索,因此不能使用/^...$/,那样只会最多匹配一次
      • 正则表达式还可以指定i标志,表示忽略大小写,m标志,表示执行多行匹配
      var r1 = /test/g;
      // 等价于:
      var r2 = new RegExp('test', 'g');
      
      var s = 'JavaScript, VBScript, JScript and ECMAScript';
      var re=/[a-zA-Z]+Script/g;
      
      // 使用全局匹配:
      re.exec(s); // ['JavaScript']
      re.lastIndex; // 10
      
      re.exec(s); // ['VBScript']
      re.lastIndex; // 20
      
  3. JSON

    • 数据类型

      • number:和JavaScript的number完全一致;
      • boolean:就是JavaScript的truefalse
      • string:就是JavaScript的string
      • null:就是JavaScript的null
      • array:就是JavaScript的Array表示方式——[]
      • object:就是JavaScript的{ ... }表示方式。
    • JSON写死了字符集必须为UTF-8

    • JSON中字符串规定必须用双引号"" ,object中的键也必须用双引号

    • 序列化

      • 将Javascript对象转为JSON对象
      • JSON.s tringify()
      'use strict';
      
      var xiaoming = {
          name: '小明',
          age: 14,
          gender: true,
          height: 1.65,
          grade: null,
          'middle-school': '\"W3C\" Middle School',
          skills: ['JavaScript', 'Java', 'Python', 'Lisp']
      };
      // 直接输出转化后的JSON字符串
      var s = JSON.stringify(xiaoming);
      console.log(s);
      
      // 按缩进输出
      JSON.stringify(xiaoming, null, '  ');
      
      // 仅输出某些键值
      JSON.stringify(xiaoming, ['name', 'skills'], '  ');
      
      // 可以传入一个函数,这样对象的每个键值对都会被函数先处理
      function convert(key, value) {
          if (typeof value === 'string') {
              return value.toUpperCase();
          }
          return value;
      }
      
      JSON.stringify(xiaoming, convert, '  ');
      
      // 可以给小明定义一个 toJSON()方法,直接返回JSON应该序列化的数据
      var xiaoming = {
          name: '小明',
          age: 14,
          gender: true,
          toJSON: function () {
              return { // 只输出name和age,并且改变了key:
                  'Name': this.name,
                  'Age': this.age
              };
          }
      };
      
      JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
      
    • 反序列化

      • 将JSON对象转为Javascript对象
      • JSON.parse()
      JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
      JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
      JSON.parse('true'); // true
      JSON.parse('123.45'); // 123.45
      
    • JSON.parse()还可以接收一个函数,用来转换解析出的属性:

      'use strict';
      var obj = JSON.parse('{"name":"小明","age":14}', function (key, value) {
          if (key === 'name') {
              return value + '同学';
          }
          return value;
      });
      console.log(JSON.stringify(obj)); // {name: '小明同学', age: 14}
      

面向对象

未完待续。。。

posted @ 2022-02-16 14:20  DreamEagle  阅读(8)  评论(0编辑  收藏  举报