基本引用类型

引用值(或者对象)是某个特定引用类型的实例新对象通过使用 new 操作符后跟一个构造函数(constructor)来创建

Date

Date 类型将日期保存为自协调世界时(UTC,Universal Time Coordinated)时间 1970 年 1 月 1 日午夜(零时)至今所经过的毫秒数,在不给 Date 构造函数传参数的情况下,创建的对象将保存当前日期和时间

Date.parse()方法接收一个表示日期的字符串参数,尝试将这个字符串转换为表示该日期的毫秒数

  • “月/日/年”,如”5/23/2019”
  • “月名 日, 年”,如”May 23, 2019”
  • “周几 月名 日 年 时:分:秒 时区”,如”Tue May 23 2019 00:00:00 GMT-0700”
  • ISO 8601 扩展格式“YYYY-MM-DDTHH:mm:ss.sssZ”,如 2019-05-23T00:00:00(只适用于兼容 ES5 的实现)
  1. let someDate = new Date(Date.parse("May 23, 2019"));

不同的浏览器对 Date 类型的实现有很多问题。比如,很多浏览器会选择用当前日期替代越界的日期,因此有些浏览器会将”January 32, 2019”解释为”February 1, 2019”。Opera 则会插入当前月的当前日,返回”January 当前日, 2019”。就是说,如果是在 9 月 21 日运行代码,会返回”January 21, 2019”。

Date.UTC()方法也返回日期的毫秒表示,但使用的是跟 Date.parse()不同的信息来生成这个值。传给 Date.UTC()的参数是年、零起点月数(1 月是 0,2 月是 1,以此类推)、日(131)、时(023)、分、秒和毫秒。这些参数中,只有前两个(年和月)是必需的。如果不提供日,那么默认为 1 日。其他参数的默认值都是 0

测试此方法在初始日期时间为 08:00:00,即传递小时传输为 1 时,输出小时时间为 9, 传递日期为 5 时,输出日期为 6,

  1. // GMT 时间 2000 年 1 月 1 日零点
  2. let y2k = new Date(Date.UTC(2000, 0)); // Sat Jan 01 2000 08:00:00 GMT+0800 (中国标准时间)
  3. // GMT 时间 2005 年 5 月 5 日下午 5 点 55 分 55 秒
  4. let allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55)); // Fri May 06 2005 01:55:55 GMT+0800 (中国标准时间)

Date 构造函数跟 Date.UTC()接收的参数是一样的

  1. // 本地时间 2000 年 1 月 1 日零点
  2. let y2k = new Date(2000, 0);
  3. // 本地时间 2005 年 5 月 5 日下午 5 点 55 分 55 秒
  4. let allFives = new Date(2005, 4, 5, 17, 55, 55);

Date.now()方法,返回表示方法执行时日期和时间的毫秒数。这个方法可以方便地用在代码分析中

  1. // 起始时间
  2. let start = Date.now();
  3. // 调用函数
  4. doSomething();
  5. // 结束时间
  6. let stop = Date.now(),
  7. result = stop - start;

其他方法

  1. a = new Date()
  2. Mon Nov 22 2021 23:38:53 GMT+0800 (中国标准时间)
  3. a.toLocaleString()
  4. '2021/11/22 下午11:38:53'
  5. a.toString()
  6. 'Mon Nov 22 2021 23:38:53 GMT+0800 (中国标准时间)'
  7. a.valueOf()
  8. 1637595533668
  9. a.toDateString()
  10. 'Mon Nov 22 2021'
  11. a.toTimeString()
  12. '23:38:53 GMT+0800 (中国标准时间)'

RegExp

创建:

  1. let expression = /pattern/flags

正则表达式的 pattern(模式)可以是任何简单或复杂的正则表达式,包括字符类、限定符、分组、向前查找和反向引用。每个正则表达式可以带零个或多个 flags(标记),用于控制正则表达式的行为

匹配模式的标记

  • g:全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束
  • i:不区分大小写,表示在查找匹配时忽略 pattern 和字符串的大小写
  • m:多行模式,表示查找到一行文本末尾时会继续查找
  • y:粘附模式,表示只查找从 lastIndex 开始及之后的字符串
  • u:Unicode 模式,启用 Unicode 匹配
  • s:dotAll 模式,表示元字符.匹配任何字符(包括\n 或\r)

元字符需要转义 ( [ { \ ^ $ | ) ] } ? * + .

  1. // 匹配字符串中的所有"at"
  2. let pattern1 = /at/g;
  3. // 匹配第一个"bat"或"cat",忽略大小写
  4. let pattern2 = /[bc]at/i;
  5. // 匹配第一个"[bc]at",忽略大小写
  6. let pattern2 = /\[bc\]at/i;
  7. // 匹配所有以"at"结尾的三字符组合,忽略大小写
  8. let pattern3 = /.at/gi;
  9. // 匹配所有".at",忽略大小写
  10. let pattern4 = /\.at/gi;

实例属性(部分)

  • global:布尔值,表示是否设置了 g 标记
  • ignoreCase:布尔值,表示是否设置了 i 标记

exec() 方法,该方法只接收一个参数,即要应用模式的字符串。如果找到了匹配项,则返回包含第一个匹配信息的数组;如果没找到匹配项,则返回null。返回的数组虽然是 Array 的实例,但包含两个额外的属性:index 和 input。index 是字符串中匹配模式的起始位置,input 是要查找的字符串。这个数组的第一个元素是匹配整个模式的字符串,其他元素是与表达式中的捕获组匹配的字符串。如果模式中没有捕获组,则数组只包含一个元素

  1. let a = /a/g
  2. b = a.exec("babaa")
  3. // b : ['a',index:0,input:'babaa',groups:undefined]
  4. // 设置了全局标记,则每次调用 exec()方法会返回一个匹配的信息。如果没有设置全局标记,则无论对同一个字符串调用多少次 exec(),也只会返回第一个匹配的信息
  5. c = a.exec('babaa')
  6. // c : ['a',index:3,input:'babaa',groups:undefined]

test() 方法,该接收一个字符串参数。如果输入的文本与模式匹配,则参数返回 true,否则返回 false

正则表达式的 valueOf()方法返回正则表达式本身

构造函数属性—简写形式需要使用[]调用,Opera浏览器不支持简写形式

  1. let text = "this has been a short summer";
  2. let pattern = /(.)hort/g;
  3. if (pattern.test(text)) {
  4. console.log(RegExp.input); // this has been a short summer 最后搜索的字符串(非标准特性)--($_ )
  5. console.log(RegExp.leftContext); // this has been a input 字符串中出现在 lastMatch 前面的文本--($`)
  6. console.log(RegExp.rightContext); // summer input 字符串中出现在 lastMatch 后面的文本--($' )
  7. console.log(RegExp.lastMatch); // short 最后匹配的文本 -- ($& )
  8. console.log(RegExp.lastParen); // s 最后匹配的捕获组(非标准特性)--($+)
  9. }

原始值包装类型

String

每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象,从而暴露出操作原始值的各种方法

  1. let s1 = 'some'; // undefined
  2. s1.color = 'red'; // 'red'
  3. console.log(s1.color); // undefined

这里的第二行代码尝试给字符串 s1 添加了一个 color 属性。可是,第三行代码访问 color 属性时,它却不见了。原因就是第二行代码运行时会临时创建一个 String 对象,而当第三行代码执行时,这个对象已经被销毁了。实际上,第三行代码在这里创建了自己的 String 对象,但这个对象没有 color 属性。

  1. let str1 = new Object('some'); // let str1 = new String('some')
  2. str1.color = 'red'; // 'red'
  3. console.log(str1.color); // red
  4. //String {'some', color: 'red'}
  • 字符串截取 slice()、substr()和 substring()
  • 字符串位置 indexOf()和 lastIndexOf()
  • 字符串包含 startsWith()、endsWith()和 includes()
  • 清除空格 trim()
  • 重复 repeat()
  • 复制 padStart()和 padEnd()
  • 匹配 match()
  • 替换 replace()
  • 比较 localeCompare()

Boolean

  1. let falseObject = new Boolean(false);
  2. let result = falseObject && true;
  3. console.log(result); // true
  4. let falseValue = false;
  5. result = falseValue && true;
  6. console.log(result); // false

使用原始Boolean值,建议永远不要使用 Boolean 对象

Number

  1. // toString() 方法返回指定 Number 对象的字符串表示形式。
  2. let num = 10;
  3. console.log(num.toString()); // "10"
  4. console.log(num.toString(2)); // "1010"
  5. console.log(num.toString(8)); // "12"
  6. console.log(num.toString(10)); // "10"
  7. console.log(num.toString(16)); // "a"
  8. // toFixed() 方法使用定点表示法来格式化一个数。 如果数值本身的小数位超过了参数指定的位数,则四舍五入到最接近的小数位
  9. let num = 10;
  10. console.log(num.toFixed(2)); // "10.00"
  11. let num = 10.005;
  12. console.log(num.toFixed(2)); // "10.01"
  13. // toPrecision() 方法以指定的精度返回该数值对象的字符串表示。

与 Boolean 对象类似,Number 对象也为数值提供了重要能力。但是,考虑到两者存在同样的潜在问题,因此并不建议直接实例化 Number 对象

原始数值在调用 typeof 时始终返回”number”,而 Number 对象则返回”object”。类似地,Number对象是 Number 类型的实例,而原始数值不是

单例内置对象

内置对象: “任何由 ECMAScript 实现提供、与宿主环境无关,并在 ECMAScript程序开始执行时就存在的对象,包括 Object, Array, String, Global, Math等

Global

在全局作用域中定义的变量和函数都会变成 Global 对象的属性

  • URL 编码方法: encodeURI()和 encodeURIComponent() 解码: decodeURI()和 decodeURIComponent()。
  • eval() 慎用

浏览器将 window 对象实现为 Global对象的代理

Math

ECMAScript 提供了 Math 对象作为保存数学公式、信息和计算的地方。Math 对象提供了一些辅助计算的属性和方法

Math 对象上提供的计算要比直接在 JavaScript 实现的快得多,因为 Math 对象上的计算使用了 JavaScript 引擎中更高效的实现和处理器指令。但使用 Math 计算的问题是精度会因浏览器、操作系统、指令集和硬件而异

  • min()和 max()方法
  • 舍入方法: Math.ceil()、Math.floor()、Math.round()和 Math.fround()
  • 随机数方法: random()

Math.random()方法在这里出于演示目的是没有问题的。如果是为了加密而需要生成随机数(传给生成器的输入需要较高的不确定性),那么建议使用 window.crypto. getRandomValues()

  1. let values = [1, 2, 3, 4, 5, 6, 7, 8];
  2. let max = Math.max(...val);
  1. function selectFrom(lowerValue, upperValue) {
  2. let choices = upperValue - lowerValue + 1;
  3. return Math.floor(Math.random() * choices + lowerValue);
  4. }
  5. let num = selectFrom(2,10);
  6. console.log(num); // 2~10 范围内的值,其中包含 2 和 10

小结

JavaScript 中的对象称为引用值,几种内置的引用类型可用于创建特定类型的对象

  • 引用值与传统面向对象编程语言中的类相似,但实现不同
  • Date 类型提供关于日期和时间的信息,包括当前日期、时间及相关计算。
  • RegExp 类型是 ECMAScript 支持正则表达式的接口,提供了大多数基础的和部分高级的正则表达式功能

JavaScript 比较独特的一点是,函数实际上是 Function 类型的实例,也就是说函数也是对象。因为函数也是对象,所以函数也有方法,可以用于增强其能力

由于原始值包装类型的存在,JavaScript 中的原始值可以被当成对象来使用。有 3 种原始值包装类型:Boolean、Number 和 String。它们都具备如下特点

  • 每种包装类型都映射到同名的原始类型
  • 以读模式访问原始值时,后台会实例化一个原始值包装类型的对象,借助这个对象可以操作相应的数据
  • 涉及原始值的语句执行完毕后,包装对象就会被销毁

当代码开始执行时,全局上下文中会存在两个内置对象:Global 和 Math。其中,Global 对象在大多数 ECMAScript 实现中无法直接访问。不过,浏览器将其实现为 window 对象。所有全局变量和函数都是 Global 对象的属性。Math 对象包含辅助完成复杂计算的属性和方法