5.1 Date
    Date类型将日期保存为自协调世界时(UTC, Universal Time Coordinated)时间1970年1月1日午夜(零时)至今所经过的毫秒数。
    使用这种存储格式,Date类型可以精确表示1970年1月1日之前及之后285616年的日期。
    要创建日期对象,就使用new操作符来调用Date构造函数:
    let code = new Date()
    不传参数,创建的对象将保存当前日期和时间。
    要基于其他日期和时间创建日期对象,必须传入其毫秒表示(UNIX纪元1970年1月1日午夜之后的毫秒数)。ECMAScript为此提供了两个辅助方法:Date.parse()和Date.UTC()。
    Date.parse()方法接收一个表示日期的字符串参数,尝试将这个字符串转换为表示该日期的毫秒数。
    Date.UTC()方法也返回日期的毫秒表示。
    传给Date.UTC()的参数是年、零起点月数(1月是0,2月是1,以此类推)、日(1~31)、时(0~23)、分、秒和毫秒。
    这些参数中,只有前两个(年和月)是必需的。如果不提供日,那么默认为1日。其他参数的默认值都是0。
    Date.parse(),Date.UTC()会被Date构造函数隐式调用

    自协调世界时(UTC, Universal Time Coordinated),现在作为世界标准时间使用
    GMT日期,即格林尼治标准时间,也就是世界时。但由于地球自转不均匀不规则,导致GMT不精确,现在已经不再作为世界标准时间使用。

    Date.UTC()被Date构造函数隐式调用时:这种情况下创建的是本地日期,不是GMT日期
    Date.now()方法,返回表示方法执行时日期和时间的毫秒数。
    image.png
    5.1.1 继承的方法
    Date类型重写了toLocaleString()、toString()和valueOf()方法
    Date类型的toLocaleString()方法返回与浏览器运行的本地环境一致的日期和时间。
    这通常意味着格式中包含针对时间的AM(上午)或PM(下午),但不包含时区信息(具体格式可能因浏览器而不同)。
    toString()方法通常返回带时区信息的日期和时间,而时间也是以24小时制(0~23)表示的。
    valueOf()方法根本就不返回字符串,这个方法被重写后返回的是日期的毫秒表示。
    因此,操作符(如小于号和大于号)可以直接使用它返回的值
    例子:
    image.png
    5.1.2 日期格式化方法
    5.1.3 日期/时间组件方法
    Date类型剩下的方法直接涉及取得或设置日期值的特定部分。
    注意表中“UTC日期”,指的是没有时区偏移(将日期转换为GMT)时的日期。
    image.png
    image.png
    5.2 RegExp
    ECMAScript通过RegExp类型支持正则表达式。
    正则表达式使用类似Perl的简洁语法来创建:
    image.png
    pattern(模式)可以是任何简单或复杂的正则表达式,包括字符类、限定符、分组、向前查找和反向引用。
    每个正则表达式可以带零个或多个flags(标记),用于控制正则表达式的行为。
    下面给出了表示匹配模式的标记:
    ❑ g:全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束。
    ❑ i:不区分大小写,表示在查找匹配时忽略pattern和字符串的大小写。
    ❑ m:多行模式,表示查找到一行文本末尾时会继续查找。
    ❑ y:粘附模式,表示只查找从lastIndex开始及之后的字符串。
    ❑ u: Unicode模式,启用Unicode匹配。
    ❑ s: dotAll模式,表示元字符.匹配任何字符(包括\n或\r)。
    image.png
    所有元字符在模式中也必须转义,包括:
    image.png
    元字符在正则表达式中都有一种或多种特殊功能,所以要匹配上面这些字符本身,就必须使用反斜杠来转义。
    image.png
    正则表达式也可以使用RegExp构造函数来创建,它接收两个参数:模式字符串和(可选的)标记字符串。
    image.png
    注意,RegExp构造函数的两个参数都是字符串。因为RegExp的模式参数是字符串,所以在某些情况下需要二次转义。所有元字符都必须二次转义,包括转义字符序列,如\n(\转义后的字符串是\,在正则表达式字符串中则要写成\\)
    5.2.1 RegExp实例属性
    5.2.2 RegExp实例方法
    RegExp实例的主要方法是exec(),主要用于配合捕获组使用。
    这个方法只接收一个参数,即要应用模式的字符串。
    如果找到了匹配项,则返回包含第一个匹配信息的数组;
    如果没找到匹配项,则返回null。
    返回的数组虽然是Array的实例,但包含两个额外的属性:index和input。
    index是字符串中匹配模式的起始位置,input是要查找的字符串。
    这个数组的第一个元素是匹配整个模式的字符串,其他元素是与表达式中的捕获组匹配的字符串。
    如果模式中没有捕获组,则数组只包含一个元素。
    正则表达式的另一个方法是test(),接收一个字符串参数。
    如果输入的文本与模式匹配,则参数返回true,否则返回false。
    这个方法适用于只想测试模式是否匹配,而不需要实际匹配内容的情况。
    test()经常用在if语句中:
    image.png
    继承的方法toLocaleString()和toString()都返回正则表达式的字面量表示
    正则表达式的valueOf()方法返回正则表达式本身
    5.2.3 RegExp构造函数属性
    5.2.4 模式局限
    缺少Perl语言中的一些高级特性。
    下列特性目前还没有得到ECMAScript的支持(想要了解更多信息,可以参考Regular-Expressions.info网站):
    ❑ \A和\Z锚(分别匹配字符串的开始和末尾)
    ❑ 联合及交叉类
    ❑ 原子组
    ❑ x(忽略空格)匹配模式
    ❑ 条件式匹配
    ❑ 正则表达式注释
    虽然还有这些局限,但ECMAScript的正则表达式已经非常强大,可以用于大多数模式匹配任务。
    5.3 原始值包装类型
    为了方便操作原始值,ECMAScript提供了3种特殊的引用类型:Boolean、Number和String。
    这些类型具有本章介绍的其他引用类型一样的特点,但也具有与各自原始类型对应的特殊行为。
    每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象,从而暴露出操作原始值的各种方法。
    image.png
    当第二行访问s1时,是以读模式访问的,也就是要从内存中读取变量保存的值。
    在以读模式访问字符串值的任何时候,后台都会执行以下3步:
    (1)创建一个String类型的实例;
    (2)调用实例上的特定方法;
    (3)销毁实例。
    可以把这3步想象成执行了如下3行ECMAScript代码:
    image.png
    引用类型与原始值包装类型的主要区别在于对象的生命周期。在通过new实例化引用类型后,得到的实例会在离开作用域时被销毁,而自动创建的原始值包装对象则只存在于访问它的那行代码执行期间。这意味着不能在运行时给原始值添加属性和方法。
    比如下面的例子:
    image.png
    第二行代码尝试给字符串s1添加了一个color属性。可是,第三行代码访问color属性时,它却不见了。原因就是第二行代码运行时会临时创建一个String对象,而当第三行代码执行时,这个对象已经被销毁了。实际上,第三行代码在这里创建了自己的String对象,但这个对象没有color属性。
    另外,Object构造函数作为一个工厂方法,能够根据传入值的类型返回相应原始值包装类型的实例。
    比如:
    image.png
    如果传给Object的是字符串,则会创建一个String的实例。
    如果是数值,则会创建Number的实例。
    布尔值则会得到Boolean的实例。
    注意,使用new调用原始值包装类型的构造函数,与调用同名的转型函数并不一样。
    例如:
    image.png
    变量number中保存的是一个值为25的原始数值,而变量obj中保存的是一个Number的实例
    5.3.1 Boolean
    Boolean是对应布尔值的引用类型。要创建一个Boolean对象,就使用Boolean构造函数并传入true或false
    如下例所示:
    image.png
    例子:
    image.png
    我们创建一个值为false的Boolean对象。然后,在一个布尔表达式中通过&&操作将这个对象与一个原始值true组合起来。在布尔算术中,false && true等于false。可是,这个表达式是对falseObject对象而不是对它表示的值(false)求值。前面刚刚说过,所有对象在布尔表达式中都会自动转换为true,因此falseObject在这个表达式里实际上表示一个true值。那么true && true当然是true。
    除此之外,原始值和引用值(Boolean对象)还有几个区别。
    首先,typeof操作符对原始值返回”boolean”,但对引用值返回”object”。
    同样,Boolean对象是Boolean类型的实例,在使用instaceof操作符时返回true,但对原始值则返回false
    如下所示:
    image.png
    理解原始布尔值和Boolean对象之间的区别非常重要,强烈建议永远不要使用后者。
    5.3.2 Number
    Number是对应数值的引用类型。
    要创建一个Number对象,就使用Number构造函数并传入一个数值
    如下例所示:
    image.png
    valueOf()方法返回Number对象表示的原始数值
    toLocaleString()toString()两个方法返回数值字符串。toString()方法可选地接收一个表示基数的参数,并返回相应基数形式的数值字符串
    将数值格式化为字符串的方法:
    toFixed()方法返回包含指定小数点位数的数值字符串
    toExponential(),返回以科学记数法(也称为指数记数法)表示的数值字符串。toExponential()也接收一个参数,表示结果中小数的位数
    toPrecision()方法会根据情况返回最合理的输出结果,可能是固定长度,也可能是科学记数法形式。这个方法接收一个参数,表示结果中数字的总位数(不包含指数)
    ES6新增了Number.isInteger()方法,用于辨别一个数值是否保存为整数
    5.3.3 String
    String是对应字符串的引用类型。
    要创建一个String对象,使用String构造函数并传入一个数值,如下例所示:
    3个继承的方法valueOf()、toLocaleString()和toString()都返回对象的原始字符串值。
    每个String对象都有一个length属性,表示字符串中字符的数量
    String类型提供了很多方法来解析和操作字符串。
    1.JavaScript字符
    JavaScript字符串由16位码元(code unit)组成。对多数字符来说,每16位码元对应一个字符。换句话说,字符串的length属性表示字符串包含多少16位码元
    charAt()方法返回给定索引位置的字符,由传给方法的整数参数指定。
    具体来说,这个方法查找指定索引位置的16位码元,并返回该码元对应的字符
    使用charCodeAt()方法可以查看指定码元的字符编码。这个方法返回指定索引位置的码元值,索引以整数指定。
    fromCharCode()方法用于根据给定的UTF-16码元创建字符串中的字符。这个方法可以接受任意多个数值,并返回将所有数值对应的字符拼接起来的字符串
    2.normalize()方法
    3.字符串操作方法
    concat(),用于将一个或多个字符串拼接成一个新字符串。
    concat()方法可以接收任意多个参数,因此可以一次性拼接多个字符串
    3个从字符串中提取子字符串的方法:slice()、substr()和substring()
    这3个方法都返回调用它们的字符串的一个子字符串,而且都接收一或两个参数。第一个参数表示子字符串开始的位置,第二个参数表示子字符串结束的位置。
    对slice()和substring()而言,第二个参数是提取结束的位置(即该位置之前的字符会被提取出来);
    对substr()而言,第二个参数表示返回的子字符串数量。
    任何情况下,省略第二个参数都意味着提取到字符串末尾。
    与concat()方法一样,slice()、substr()和substring()也不会修改调用它们的字符串,而只会返回提取到的原始新字符串值。
    当某个参数是负值时,这3个方法的行为又有不同。比如,
    slice()方法将所有负值参数都当成字符串长度加上负参数值;
    substr()方法将第一个负参数值当成字符串长度加上该值,将第二个负参数值转换为0;
    substring()方法会将所有负参数值都转换为0
    image.png
    4.字符串位置方法
    在字符串中定位子字符串:indexOf()lastIndexOf()
    这两个方法从字符串中搜索传入的字符串,并返回位置(如果没找到,则返回-1)
    两者的区别在于,indexOf()方法从字符串开头开始查找子字符串,而lastIndexOf()方法从字符串末尾开始查找子字符串。
    这两个方法都可以接收可选的第二个参数,表示开始搜索的位置。
    这意味着,indexOf()会从这个参数指定的位置开始向字符串末尾搜索,忽略该位置之前的字符;
    lastIndexOf()则会从这个参数指定的位置开始向字符串开头搜索,忽略该位置之后直到字符串末尾的字符。
    5.字符串包含方法
    ECMAScript 6增加了3个用于判断字符串中是否包含另一个字符串的方法:startsWith()、endsWith()和includes()。
    这些方法都会从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值。
    区别:
    startsWith()检查开始于索引0的匹配项
    endsWith()检查开始于索引(string.length - substring.length)的匹配项
    includes()检查整个字符串
    startsWith()和includes()方法接收可选的第二个参数,表示开始搜索的位置。如果传入第二个参数,则意味着这两个方法会从指定位置向着字符串末尾搜索,忽略该位置之前的所有字符
    endsWith()方法接收可选的第二个参数,表示应该当作字符串末尾的位置。如果不提供这个参数,那么默认就是字符串长度。如果提供这个参数,那么就好像字符串只有那么多字符一样
    6.trim()方法
    ECMAScript在所有字符串上都提供了trim()方法。这个方法会创建字符串的一个副本,删除前、后所有空格符,再返回结果
    trimLeft()和trimRight()方法分别用于从字符串开始和末尾清理空格符。
    7.repeat()方法
    ECMAScript在所有字符串上都提供了repeat()方法。
    这个方法接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果。
    image.png
    8.padStart()和padEnd()方法
    padStart()和padEnd()方法会复制字符串
    如果小于指定长度,则在相应一边填充字符,直至满足长度条件。
    这两个方法的第一个参数是长度,第二个参数是可选的填充字符串,默认为空格(U+0020)
    9.字符串迭代与解构
    10.字符串大小写转换
    4个方法:toLowerCase()、toLocaleLowerCase()、toUpperCase()和toLocaleUpperCase()
    toLowerCase()和toUpperCase()方法是原来就有的方法
    toLocaleLowerCase()和toLocaleUpperCase()方法旨在基于特定地区实现
    通常,如果不知道代码涉及什么语言,则最好使用地区特定的转换方法
    11.字符串模式匹配方法
    第一个是match()方法,这个方法本质上跟RegExp对象的exec()方法相同。
    match()方法接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象
    另一个查找模式的字符串方法是search()
    这个方法唯一的参数与match()方法一样:正则表达式字符串或RegExp对象。
    这个方法返回模式第一个匹配的位置索引,如果没找到则返回-1。search()始终从字符串开头向后匹配模式。
    为简化子字符串替换操作,ECMAScript提供了replace()方法
    这个方法接收两个参数,第一个参数可以是一个RegExp对象或一个字符串(这个字符串不会转换为正则表达式),第二个参数可以是一个字符串或一个函数。
    如果第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字符串,第一个参数必须为正则表达式并且带全局标记
    最后一个与模式匹配相关的字符串方法是split()
    这个方法会根据传入的分隔符将字符串拆分成数组。
    作为分隔符的参数可以是字符串,也可以是RegExp对象。(字符串分隔符不会被这个方法当成正则表达式。)
    还可以传入第二个参数,即数组大小,确保返回的数组不会超过指定大小。
    12.localeCompare()方法
    最后一个方法是localeCompare(),这个方法比较两个字符串,返回如下3个值中的一个。
    ❑ 如果按照字母表顺序,字符串应该排在字符串参数前头,则返回负值。(通常是-1,具体还要看与实际值相关的实现。)
    ❑ 如果字符串与字符串参数相等,则返回0。
    ❑ 如果按照字母表顺序,字符串应该排在字符串参数后头,则返回正值。(通常是1,具体还要看与实际值相关的实现。)
    13.HTML方法
    这些方法基本上已经没有人使用了,因为结果通常不是语义化的标记。
    5.4 单例内置对象
    ECMA-262对内置对象的定义是“任何由ECMAScript实现提供、与宿主环境无关,并在ECMAScript程序开始执行时就存在的对象”。
    这就意味着,开发者不用显式地实例化内置对象,因为它们已经实例化好了。
    前面我们已经接触了大部分内置对象,包括Object、Array和String。本节介绍ECMA-262定义的另外两个单例内置对象:Global和Math。
    5.4.1 Global
    Global对象是ECMAScript中最特别的对象,因为代码不会显式地访问它。
    在全局作用域中定义的变量和函数都会变成Global对象的属性。
    1.URL编码方法
    encodeURI()和encodeURIComponent()方法用于编码统一资源标识符(URI),以便传给浏览器。
    有效的URI不能包含某些字符,比如空格。
    使用URI编码方法来编码URI可以让浏览器能够理解它们,同时又以特殊的UTF-8编码替换掉所有无效字符。ecnodeURI()方法用于对整个URI进行编码。
    encodeURIComponent()方法用于编码URI中单独的组件
    区别:encodeURI()不会编码属于URL组件的特殊字符,比如冒号、斜杠、问号、井号,而encodeURIComponent()会编码它发现的所有非标准字符
    注:一般来说,使用encodeURIComponent()应该比使用encodeURI()的频率更高,这是因为编码查询字符串参数比编码基准URI的次数更多
    2.eval()方法
    可能是整个ECMAScript语言中最强大的了,它就是eval()
    这个方法就是一个完整的ECMAScript解释器,它接收一个参数,即一个要执行的ECMAScript(JavaScript)字符串。
    例子:
    image.png
    这行代码的功能与下一行等价:
    image.png
    通过eval()定义的任何变量和函数都不会被提升,这是因为在解析代码的时候,它们是被包含在一个字符串中的。它们只是在eval()执行的时候才会被创建。
    在严格模式下,在eval()内部创建的变量和函数无法被外部访问。
    注:解释代码字符串的能力是非常强大的,但也非常危险。在使用eval()的时候必须极为慎重,特别是在解释用户输入的内容时。因为这个方法会对XSS利用暴露出很大的攻击面。恶意用户可能插入会导致你网站或应用崩溃的代码。
    3.Global对象属性
    像undefined、NaN和Infinity等特殊值都是Global对象的属性。
    所有原生引用类型构造函数,比如Object和Function,也都是Global对象的属性。
    下表列出了所有这些属性:
    image.png
    4.window对象
    虽然ECMA-262没有规定直接访问Global对象的方式,但浏览器将window对象实现为Global对象的代理。
    因此,所有全局作用域中声明的变量和函数都变成了window的属性
    5.4.2 Math
    ECMAScript提供了Math对象作为保存数学公式、信息和计算的地方。
    Math对象提供了一些辅助计算的属性和方法。
    注:Math对象上提供的计算要比直接在JavaScript实现的快得多,因为Math对象上的计算使用了JavaScript引擎中更高效的实现和处理器指令。但使用Math计算的问题是精度会因浏览器、操作系统、指令集和硬件而异。
    1.Math对象属性
    Math对象有一些属性,主要用于保存数学中的一些特殊值
    2.min()和max()方法
    Math对象也提供了很多辅助执行简单或复杂数学计算的方法。
    min()和max()方法用于确定一组数值中的最小值和最大值。这两个方法都接收任意多个参数
    要知道数组中的最大值和最小值,可以像下面这样使用扩展操作符:
    image.png
    3.舍入方法
    把小数值舍入为整数的4个方法:Math.ceil()、Math.floor()、Math.round()和Math.fround()。
    ❑ Math.ceil()方法始终向上舍入为最接近的整数。
    ❑ Math.floor()方法始终向下舍入为最接近的整数。
    ❑ Math.round()方法执行四舍五入。
    ❑ Math.fround()方法返回数值最接近的单精度(32位)浮点值表示。
    4.random()方法
    Math.random()方法返回一个0~1范围内的随机数,其中包含0但不包含1。
    注:Math.random()方法在这里出于演示目的是没有问题的。如果是为了加密而需要生成随机数(传给生成器的输入需要较高的不确定性),那么建议使用window.crypto.getRandomValues()。
    5.其他方法
    Math对象还有很多涉及各种简单或高阶数运算的方法。