window.Date、Math、JSON用法解读

目录

  • 一、前言
  • 二、window.Date
    • 1. 构造Date对象
    • 2. Date的静态属性和方法
      • (1). 静态属性
      • (2). 静态方法
    • 3. Date的原型方法
      • (1). 实例属性
      • (2). getter类
      • (3). setter类
      • (4). conversion getter类
  • 三、window.Math
    • 1. Math的数学常量
    • 2. Math的数学函数
  • 四、window.JSON
    • 1. JSON语法简介
    • 2. JSON的用法
  • 总结

一、前言

相信只要对前端有所了解的同学,对window对象的DateMathJSON这三个原生对象(或构造函数)都不会陌生,不过可能并不是所有同学都全面学习过这三个原生对象。本文就将帮大家梳理一下关于这三个原生对象的主要知识点。

首先我们先来简述这三个原生对象的作用。

window.Date是浏览器提供的日期接口对象,主要用于访问日期相关的函数或属性。比如我们想获取当前日期,可以像下面一样:

> let date = new Date();
> date
< Tue Aug 04 2020 22:11:28 GMT+0800 (中国标准时间)

这样就得到了当前时间。

调用日期对象的原型方法,还可以单独获取年月日时分秒等信息,另外它还包含对时区的支持。基本上与时间相关的操作都可以借助window.Date完成。

window.Math提供了对常见的数学运算,以及一些数学常量的支持。下面是一些常用的函数或常量:

Math.abs();  // 求绝对值
Math.sin();  // 求正弦值
Math.floor();  // 数值的向下取整
Math.pow();  // 幂运算
Math.PI;  // 圆周率
Math.E;  // 自然常量
Math.SQRT2;  // 2的平方根
.....

还有非常多的函数和常量,我们后续会一一列举。

window.JSON是浏览器提供的操作JSON对象的接口。这个对象最重要的两个方法就是JSON.parseJSON.stringify,前者可以将一个JSON字符串解析为一个JavaScript对象,而后者可以将一个JavaScript对象字符串化(即转为JSON字符串)。两者是互逆的操作。

二、window.Date

Date是浏览器为开发者提供的访问日期的构造函数,该对象基于Unix Time Stamp,即自1970年1月1日起所经过的毫秒数,因此Date对象理论上最多可以精确到毫秒(实际上一般只能精确到秒,参考自MDN文档)。

1. 构造Date对象

构造一个Date对象需要使用new关键字,如new Date()。在中国,构造出的时间默认为北京时间(但是当用getTime()获取Unix时间戳时,是以格林尼治标准时间为基准)。它接受的参数可以有四种方式:

  1. 没有参数,得到的日期对象对应的就是构造该对象时的日期和时间,一般可理解为当前时间。构造出的对象默认为北京时间(即东八区标准时间)。
> new Date();  // 2020年8月5日
< Wed Aug 05 2020 21:18:28 GMT+0800 (中国标准时间)
  1. Unix时间戳,即从1970年1月1日0时(格林尼治标准时间)起经过的毫秒数,是一个整数,如本文的写作时的时间戳为1596633508424
> new Date(1596633508424);
< Wed Aug 05 2020 21:18:28 GMT+0800 (中国标准时间)
  1. 时间戳字符串,表示一个日期的字符串,如new Date('2020-8-5')。这种方式对字符串的格式要求不是很严格,如new Date('2020-08-05 12:00')也可以被正确解析。该类字符串的规范请参考IETF-compliant RFC 2822 timestamps,不过一般直接打开浏览器控制台,测试一下是否能解析即可。
> new Date('2020-8-5');  // 2020年8月5日
< Wed Aug 05 2020 00:00:00 GMT+0800 (中国标准时间)

> new Date('2020-08-05 12:00');  // 2020年8月5日12点
< Wed Aug 05 2020 12:00:00 GMT+0800 (中国标准时间)

> new Date('Wed Aug 05 2020 12:00:00 GMT+0800 (中国标准时间)');
< Wed Aug 05 2020 12:00:00 GMT+0800 (中国标准时间)
  1. 依次提供日期与时间等参数,格式为new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])。这种格式的构造函数要求至少需要传入年份和月份(这里月份是从0开始计算的,因此传入7时表示8月份),其他未传的参数自动填充为最小值(日期最小为1,其他最小为0)。当只传入年份时,得到的时间会是1970年1月1日。
> new Date(2020);  // 只传年份返回的结果是1970年1月1日
< Thu Jan 01 1970 08:00:02 GMT+0800 (中国标准时间)

> new Date(2020, 7);  // 2020-8-1 00:00:00
< Tue Aug 01 2020 00:00:00 GMT+0800 (中国标准时间)

> new Date(2020, 7, 5, 21);  // 2020-8-5 21:00:00
< Wed Aug 05 2020 21:00:00 GMT+0800 (中国标准时间)

再次提醒,Date的月份是从0开始计算的,因此第四种传参方式中的月份传入整数7时,实际上代表的是8月份。同样的,调用date.getMonth()获取月份时返回的值也是7。传入字符串格式的月份时没有该问题(如第三种传参方式)。

除了上面四种格式,Date也可以不使用new关键字(不建议这样做),此时返回的是字符串格式的时间,而不是Date对象。

> Date()
< "Wed Aug 05 2020 21:38:01 GMT+0800 (中国标准时间)"

如果第四种方式所传入的参数超过正确范围,则相邻的参数可能会自动调整,如:

> new Date(2019, 13, 1); // 调整为2020年2月1日
< Sat Feb 01 2020 00:00:00 GMT+0800 (中国标准时间)

月份的最大值为11,即12月。当传入13时,年份自动加一,月份变为2月份。

2. Date的静态属性和方法

这些属性和方法属于Date构造函数本身,直接通过Date调用。

(1). 静态属性

  1. Date.length:值为7,即Date构造函数最多支持的参数个数。

(2). 静态方法

  1. Date.now():返回自1970年1月1日0时(以格林尼治标准时间为基准)至今经过的毫秒数,等价于(new Date()).getTime()
  2. Date.parse():将一个日期字符串解析为日期对象的方法,调用Date.parse(timeString)new Date(timeString)的值一致。由于浏览器的差异,这种方式不完全可靠。
  3. Date.UTC(),接收和上述第四种传参方式同样的参数,即必传年、月,选传日、时、分、秒、毫秒,返回的是从1970年1月1日零时起所经过的毫秒数。

3. Date的原型方法

以下示例均以let date = new Date()语句构造出的date实例为基准,转换为常规时间为2020-8-5 22:10:00

> let date = new Date();
< Wed Aug 05 2020 22:10:00 GMT+0800 (中国标准时间)
< // 2020-8-5 22:10:00

(1). 实例属性

  1. Date.prototype.constructor:即Date构造函数自身。由于Date构造函数是C++实现的,因此在控制台无法查看其具体实现代码。
> Date.prototype.constructor
< ƒ Date() { [native code] }

(2). getter类

以下方法用于从date实例中提取一部分参数,如年份、月份等,仍以2020-08-05 22:10:00为例。

  1. Date.prototype.getDate():获取日期。如date.getDate()值为5,即日期为5号。
  2. Date.prototype.getDay():获取当日为当周的第几天(0 ~ 6),0表示周日,1表示周一,以此类推。如date.getDay()返回3,即周三。
  3. Date.prototype.getFullYear():返回年份。如date.getFullYear()返回2020。
  4. Date.prototype.getHours():返回小时数。如date.getHours()返回22,值区间为0~23。
  5. Date.prototype.getMilliseconds():返回毫秒数。
  6. Date.prototype.getMinutes():获取分钟数。date.getMinutes()返回10。
  7. Date.prototype.getMonth():获取月份,从0开始计数,有效值为0~11。这里date.getMonth()返回7,如需转为实际月份,请手动加一。
  8. Date.prototype.getSeconds():获取秒数。date.getSeconds()返回0。
  9. Date.prototype.getTime():返回自1970年1月1日0时起经过的毫秒数。
  10. Date.prototype.getTimezoonOffset():获取当前时区的时区偏移,以分钟计数。如北京位于东八区,早于格林尼治标准时间480分钟,因此date.getTimezoonOffset()返回-480。
  11. Date.getUTCDate()/getUTCDay()/getUTCFullYear()/getUTCHours()/getUTCMilliseconds()/getUTCMinutes()/getUTCMonth()/getUTCSeconds():这些是以上方法的世界时版本,换句话说,这几个函数返回的是此时的格林尼治时间,适合跨时区使用。
  12. Date.prototype.getYear():已废弃,请使用getFullYear()代替。返回非标准的年份,一般只返回年份的后2~3位。

(3). setter类

  1. Date.prototype.setDate():根据本地时间设置日期。如date.setDate(6)可将date实例的日期设为6号,以下方法同理。
  2. Date.prototype.setFullYear():设置年份。
  3. Date.prototype.setHours():设置小时数。
  4. Date.prototype.setMilliseconds():设置毫秒数。
  5. Date.prototype.setMinutes():设置分钟数。
  6. Date.prototype.setMonth():设置月份,从0开始计数。
  7. Date.prototype.setSeconds():设置秒数。
  8. Date.prototype.setTime():指定从1970年1月1日0时起的毫秒数,相应的其他参数都会变化,允许传负值,此时的时间早于1970年。
  9. Date.setUTCDate()/setUTCDay()/setUTCFullYear()/setUTCHours()/setUTCMilliseconds()/setUTCMinutes()/setUTCMonth()/setUTCSeconds():根据世界时设置日期对象的值。此时传入的参数被视为格林尼治时间,因此当执行date.setUTCHours(0)时,实际设置的是北京时间8点钟(格林尼治的0点正好是北京时间8点),也就是说再调用date.getHours()会返回8。
  10. Date.prototype.setYear():已废弃,请使用setFullYear()

(4). conversion getter类

这类方法用于转换日期格式。

  1. Date.prototype.toDateString():以人类易读的方式显示日期,会去掉时间部分。如:
> let date = new Date();
< Wed Aug 05 2020 22:10:00 GMT+0800 (中国标准时间)

> date.toDateString();
> "Wed Aug 05 2020"  // 2020年8月5号,周三
  1. Date.prototype.toISOString():将日期转为符合ISO 8601规范的字符串。注意,转换结果是以格林尼治时间为标准的,因此以下的小时数被转化成了14时,如:
> date.toISOString()
< "2020-08-05T14:10:00.000Z"
  1. Date.prototype.toJSON():该方法直接调用toISOString方法,返回上述的值。该方法是为了提供给JSON.stringify()将日期对象字符串化使用。
  2. **Date.prototype.toGMTString() **:已废弃,请使用toUTCString()
  3. Date.prototype.toLocaleDateString():返回一个日期字符串,显示格式与系统设置的地区有关(如中国大陆、中国香港等),如:
> date.toLocaleDateString();
< "2020/8/5"
  1. Date.prototype.toLocaleFormat():实验中的方法,使用格式字符串格式化日期。经测试,在目前最新的Chrome中仍不可用。
  2. Date.prototype.toLocaleString():返回一个易读的日期字符串,格式与系统设置的地区有关,如:
"2020/8/5 下午10:10:00"
  1. Date.prototype.toSource():实验中的方法,重写了Object.protorype.toSource,目前版本的Chrome仍不可用。
  2. Date.prototype.toString():将Date实例转化为字符串。如:
> date.toString();
< "Wed Aug 05 2020 22:10:00 GMT+0800 (中国标准时间)"
  1. Date.prototype.toTimeString():以人类易读的方式返回时间部分,如:
> date.toTimeString();
< "22:10:00 GMT+0800 (中国标准时间)"
  1. Date.prototype.toUTCString():把一个日期对象转为以格林尼治时区计时的字符串:
> date.toUTCString();  // 22时转为了14时
< "Wed, 05 Aug 2020 14:10:00 GMT"
  1. Date.prototype.valueOf():返回一个日期对象的原始值,这个值与getTime()得到的值是一致的,即从1970年1月1日0时起经过的毫秒数。如:
> date.valueOf();
< 1596636600000

以上就是Date相关的主要知识点,最后分享一个简单的日期的格式化函数:

function formatDate (date, formatter) {
    let normalDate = new Date(date); // 尝试转为日期对象
    if(normalDate !== 'Invalid Date'){
        let year = normalDate.getFullYear().toString();
        let month = normalDate.getMonth() + 1;
        month = month > 9 ? month.toString() : '0' + month.toString();
        let day = normalDate.getDate();
        day = day > 9 ? day.toString() : '0' + day.toString();

        let hours = normalDate.getHours();
        hours = hours > 9 ? hours.toString() : '0' + hours.toString();
        let minutes = normalDate.getMinutes();
        minutes = minutes > 9 ? minutes.toString() : '0' + minutes.toString();
        let seconds = normalDate.getSeconds();
        seconds = seconds > 9 ? seconds.toString() : '0' + seconds.toString();

        return formatter.replace('yyyy', year).replace('MM', month).replace('dd', day).replace('hh', hours).replace('mm', minutes).replace('ss',seconds);
    } else {
        throw new Error('Invalid date input:' + date);
    }
}

> formatDate(new Date, 'yyyy-MM-dd hh:mm:ss');
< "2020-08-05 22:10:00"

三、window.Math

window.Math封装了与数学运算相关的一些常量和函数,用于进行一些简单的数学计算。Math本身并不是函数,因此无法用来调用或构造实例。它内置的所有属性和方法都是直接通过Math来调用的。

1. Math的数学常量

  1. Math.E,即自然对数的底数e,在数学上称为欧拉常量,值约为2.718
  2. Math.LN2,2的自然对数ln2,即以常量e为底数的2的对数,值约为0.693
  3. Math.LN1010的自然对数ln10,值约为2.303
  4. Math.LOG10E,以10为底数的e的对数,值约为0.434
  5. Math.PI,圆周率,即圆的周长和直径的比值,值约为3.14159
  6. Math.SQRT1_2,二分之一的平方根,也是2的平凡根的倒数,值约为0.707
  7. Math.SQRT2,2的平方根,值约为1.414

2. Math的数学函数

  1. Math.abs(x),返回一个数的绝对值。
  2. Math.acos(x),返回一个数的反余弦值。
  3. Math.acosh(x),返回一个数的反双曲余弦值。
  4. Math.asin(x),返回一个数的反正弦值。
  5. Math.asinh(x),返回一个数的反双曲正弦值。
  6. Math.atan(x),返回一个数的反正切值。
  7. Math.atanh(x),返回一个数的反双曲正切值。
  8. Math.atan2(y, x),返回 y/x 的反正切值。
  9. Math.cbrt(x),返回一个数的立方根。
  10. Math.ceil(x),返回大于一个数的最小整数,即一个数向上取整后的值。
  11. Math.clz32(x),返回一个 32 位整数的前导零的数量。
  12. Math.cos(x),返回一个数的余弦值。
  13. Math.cosh(x),返回一个数的双曲余弦值。
  14. Math.exp(x),返回欧拉常数的参数次方,Ex,其中 x 为参数,E 是欧拉常数(2.718…,自然对数的底数)。
  15. Math.expm1(x),返回 exp(x) - 1 的值。
  16. Math.floor(x),返回小于一个数的最大整数,即一个数向下取整后的值。
  17. Math.fround(x),返回最接近一个数的单精度浮点型表示。
  18. Math.hypot([x[, y[, …]]]),返回其所有参数平方和的平方根。
  19. Math.imul(x, y),返回 32 位整数乘法的结果。
  20. Math.log(x),返回一个数的自然对数(㏒e,即 ㏑)。
  21. Math.log1p(x),返回一个数加 1 的和的自然对数(㏒e,即 ㏑)。
  22. Math.log10(x),返回一个数以 10 为底数的对数。
  23. Math.log2(x),返回一个数以 2 为底数的对数。
  24. Math.max([x[, y[, …]]]),返回零到多个数值中最大值。
  25. Math.min([x[, y[, …]]]),返回零到多个数值中最小值。
  26. Math.pow(x, y),返回一个数的 y 次幂。
  27. Math.random(),返回一个 0 到 1 之间的伪随机数。
  28. Math.round(x),返回四舍五入后的整数。
  29. Math.sign(x),返回一个数的符号,得知一个数是正数、负数还是 0。
  30. Math.sin(x),返回一个数的正弦值。
  31. Math.sinh(x),返回一个数的双曲正弦值。
  32. Math.sqrt(x),返回一个数的平方根。
  33. Math.tan(x),返回一个数的正切值。
  34. Math.tanh(x),返回一个数的双曲正切值。
  35. Math.toSource(),返回字符串 “Math”。
  36. Math.trunc(x),返回一个数的整数部分,直接去除其小数点及之后的部分。

以上内容摘自MDN文档,只需大致阅读一遍,记住几个常用的函数,其余的用到时查阅文档即可。

这里我们着重强调几个用于取近似值的函数:Math.ceil()Math.floor()Math.round()Math.trunc()。这四个函数都是用于数值取整的,但是有一些差异。

  • Math.ceil(),向上取整(ceil的中文释义为天花板),即获取大于或等于当前值的最小整数,如:
Math.ceil(1.2) === 2;
Math.ceil(3.9) === 4;
Math.ceil(1.0) === 1;
Math.ceil(-1.2) === -1;  // -1 > -1.2
  • Math.floor(),向下取整(floor的中文释义为地板),即获取小于或等于当前值的最大整数。如:
Math.floor(1.2) === 1;
Math.floor(3.9) === 3;
Math.ceil(1) === 1;
Math.ceil(-1.2) === -2;  // -2 < -1.2
  • Math.round(),以四舍五入法取整。如:
Math.round(1.2) === 1;
Math.round(3.5) === 4;
Math.round(-1.2) === -1;
  • Math.trunc(),直接截掉数值的小数位,保留整数位。对于正数来讲,它相当于向下取整;而对于负数来说,则相当于向上取整。如:
Math.trunc(1.2) === 1;
Math.trunc(-1.2) === -1;

Math没有提供对小数部分的近似方法,比如我们想四舍五入保留圆周率的五位小数,需要先将其乘以100000,使用Math.round()四舍五入后再除以100000,如:

Math.round(Math.PI * 100000) / 100000;
// 3.14159

// 以下代码则可以从百位四舍五入
Math.round(1233 / 100) * 100;
// 1200

向上、向下取整也是类似的。

Math对象还有一个极其常用的函数:Math.random(),我们也着重介绍一下。

这个函数的调用非常简单,不用传任何参数,直接调用即可产生一个0~1(含0,但不含1)之间的伪随机数。注意,该函数生成的随机数不是绝对随机的,因此不要用于安全方面,如果需要生成更安全的随机数,请使用window.crypto.getRandomValues()

该函数虽然只能生成0~1之间的数值,但经过公式转换,也可以生成一组整数。生成一个min~max含min,但不包含max)之间的整数的公式为:

Math.floor(Math.random() * (max - min) + min);

// 生成5~10(包含5,不包含10)之间的整数
Math.floor(Math.random()*5 + 5);  // 5,6,7,8,9随机
// 生成5~10(包含5,不包含10)之间的数字
Math.random()*5 + 5;

去掉Math.floor()产生的就是5~10(包含5,不包含10)之间的随机数。这里不能用Math.round()或Math.ceil()替换Math.floor(),当使用Math.round(),各个整数的概率分布是不均匀的;而使用Math.ceil()时,出现最小值的概率无限趋近于0,这两种情况通常都不是想要的。

如果想包含上限值,将max-min改为max-min+1即可。即:

Math.floor(Math.random() * (max - min + 1) + min);

// 生成5~10(包含5和10)之间的整数
Math.floor(Math.random()*6 + 5);  // 5,6,7,8,9,10随机
// 生成介于min和max的随机整数,包含上限和下限
function getRandomIntInclusive(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min; // 含最大值,含最小值 
}

四、window.JSON

1. JSON语法简介

JSON(JavaScript Object Notation,JavaScript对象简谱,可理解为JavaScript对象的简洁表示法)是符合ECMAScript规范的一个js子集,是一种轻量级的数据交换格式。目前它已经基本替代了xml(xml目前主要作为配置文件使用)格式,成为了事实的数据传输标准。

从某种意义上来说,JSON数据可以看作是一个满足特定格式的字符串。以下是一个JSON数据的例子:

{
  "name": "Carter",
  "age": 25
}

它可以大致看成这种结构:'{"name": "Carter","age": 25}'。也就是说,JSON以某种规则把js对象变成了字符串的形式,从而方便在网络中传输。

JSON仅支持6个构造字符:

  1. 左中括号[
  2. 右中括号]
  3. 左大括号{
  4. 右大括号}
  5. 冒号:
  6. 逗号,

它们的作用与js对象基本是一致的。各个字符之间允许有任意多的空格或换行符。

JSON支持的数据类型包括对象数组数字字符串,以及三个特殊的字面值:falsetruenull。js中其他类型的数据必须转为这几类数据,才可以变成JSON数据用于网络传输。

2. JSON的用法

window.JSON本身并不是普通函数,也不是构造函数,因此不能被调用或用于构造JSON实例。

window.JSON仅对外提供了两个实例方法:JSON.parse()JSON.stringify(),前者将一个JSON数据解析为JavaScript对象,后者将一个JavaScript对象处理为JSON数据,两者是一个互逆的过程。如:

> JSON.parse('{"name": "carter"}');
< { name: "Carter" }

> JSON.stringify({ name: "Carter" });
< "{"name":"carter"}"

从上述JSON.parse的用法可以看出,它可以直接用于将符合JSON标准的字符串转化为js对象,这是非常常见的用法。

而从JSON.stringify的结果则可以看出,JSON数据并不能算是真正的字符串(如果是真正的字符串,两侧应该是单引号)。这个问题在某些情况下可能会造成数据传输错误,比如当后端使用JSON包强行将JSON数据处理成字符串发送给前端时,前端很可能无法正确解析(此时前端得到的是类似"{"name":"carter"}"这样的伪字符串,它无法被还原成js对象)。

JSON的这两个互逆的方法可以非常便捷地实现对象的深度克隆,这在实际开发中非常实用和简便。如:

function clone (obj) {
  return JSON.parse(JSON.stringify(obj));
}

let a = {name: 'carter', data: {id: 123}}
let b = clone(a); // b是由a克隆而来,两者有不同的内存地址
b !== a; 

该方法的问题主要在于,它无法克隆symbol类的属性,也无法克隆函数类属性(当然还包括原型对象上的属性和方法,不过一般克隆对象时也不会克隆原型)。另外,当对象较为复杂时,它在性能上存在一定的问题。

JSON.parse其实还支持第二个参数,即reviver函数,用于在返回解析结果前执行一次处理。比如我们希望在解析之后输出所有的key,并且将所有的属性值转化为字符串,可以这样写:

JSON.parse('{"name": "carter", "age": 25}', (key, value) => {
  console.log(key);
  if (!key) return value;
  return String(value);
})

> name
> age
>     // 这里实际输出了一个空字符串
> {name: "carter", age: "25"}

注意,这里虽然只有两个key,但是reviver函数却执行了三次。多执行的那次传入的key为空字符串,而value是最终的解析结果(即我们最终得到的js对象)。所以我们专门加了一个判断,当key为空时不作任何处理,直接返回对应的value。

对应的, JSON.stringify()最多可以传三个参数,即JSON.stringify(value [, replacer [, space]])

第一个参数value是要转化为JSON的js变量,可能是对象、数组、数字、字符串、布尔值或null。

第二个参数是一个替换器,可以是函数或数组。当是函数时,它的返回值将替换该属性的原始值,如果它返回undefined,则该属性不会被字符串化到最终结果中:

JSON.stringify({name: 'carter', age: 25}, (k, v) => {
  if (!k) return v;
  return k === 'age' ? v : undefined
})

> "{"age": 25}"

与parse一样,这个replacer也被执行了三次,最后一次key为空字符串,value为字符串化的结果,所以我们先写一个判断条件过滤掉这次调用。之后我们检查key是否为age,如果是则返回对应的value,否则就返回undefined,这就使得只有age属性会被字符串化到最终结果中。当然, k !== 'age' ? v : undefined这样写就可以去掉age属性,而把其他属性字符串化。

当这个替换器是一个数组时,它就是一个白名单,只有被它罗列的属性会被字符串化:

JSON.stringify({name: 'carter', age: 25}, ['age']);

> "{"age": 25}"

需要注意的是,symbol类型的属性永远不会被字符串化,这类属性无论是否存在于白名单中,最终都会被丢弃。

第三个参数是字符串化后每个属性前要插入的空白字符数或要插入的字符,默认不插入任何字符。它可以是数字或字符串,当是数字时,会尝试在每个属性前插入该数量的空格(空格数量介于1~10之间,当传入的值小于1,会强制转为1,当大于10,会强制置为10),如:

> JSON.stringify({a: 'foo'}, ['a'], 3);
> "{
     "a": "foo"
  }"

当它是字符串时,会把它拼到属性前面,如果字符串长度大于10,则截取前10个字符:

> JSON.stringify({a: 'foo'}, ['a'], 'abc');
< "{
  abc"a": "foo"
  }"

经过测试,在不传第二个参数的情况下,直接传字符串或数字是无效的(此时它可能被当成了无效的replacer,而不是space),此时可以将第二个参数传为null来解决:

> JSON.stringify({a: 'foo'}, 3);
< "{"a":"foo"}"

> JSON.stringify({a: 'foo'}, null, 3);
< "{
     "a": "foo"
  }"

我们平时可能很少用到JSON.parseJSON.stringify的额外参数,但是当js对象和要转化的JSON属性不对等时,使用该参数可以避免额外的js操作(如使用delete删除额外属性,这会改变原始js变量的值)。

总结

本文讨论了window对象上三个重要的原生对象的相关知识点,大部分内容不需要强制记忆,但是必须掌握一些常用的方法。

你可能感兴趣的:(js基础,Date,Math,JSON)