再读红宝书(第四版) 第五章 基本引用类型

引用值(或者对象)是某个特定引用类型的实例。在 ECMAScript 中,引用类型是把数据和功能组织到一起的结构,经常被人错误地称作“类”。虽然从技术上讲 JavaScript 是一门面向对象语言,但ECMAScript 缺少传统的面向对象编程语言所具备的某些基本结构,包括类和接口。引用类型有时候也被称为对象定义,因为它们描述了自己的对象应有的属性和方法。

对象被认为是某个特定引用类型的实例。新对象通过使用 new 操作符后跟一个构造函数(constructor)来创建。构造函数就是用来创建新对象的函数,它负责创建一个只有默认属性和方法的简单对象。

date

ECMAScript 的 Date 类型参考了 Java 早期版本中的 java.util.Date。为此,Date 类型将日期保存为自协调世界时(UTC,Universal Time Coordinated)时间 1970 年 1 月 1 日午夜(零时)至今所经过的毫秒数。使用这种存储格式,Date 类型可以精确表示 1970 年 1 月 1 日之前及之后 285 616 年的日期。

在不给 Date 构造函数传参数的情况下,创建的对象将保存当前日期和时间。要基于其他日期和时间创建日期对象,必须传入其毫秒表示。如果传给 Date.parse()的字符串并不表示日期,则该方法会返回 NaN。如果直接把表示日期的字符串传给 Date 构造函数,那么 Date 会在后台调用 Date.parse()。

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

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

Date.UTC() 方法也返回日期的毫秒表示,参数是年、零起点月数.如果不提供日,那么默认为 1 日。其他

参数的默认值都是 0。

Date.parse() 一样,Date.UTC()也会被 Date 构造函数隐式调用,但有一个区别:这种情况下创建的是本地日期,不是 GMT 日期。不过 Date 构造函数跟 Date.UTC()接收的参数是一样的。

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

Date 类型重写了 toLocaleString()、toString()和 valueOf()方法。但与其他类型不同,重写后这些方法的返回值不一样。Date 类型的 toLocaleString()方法返回与浏览器运行的本地环境一致的日期和时间。这通常意味着格式中包含针对时间的 AM(上午)或 PM(下午),但不包含时区信息(具体格式可能因浏览器而不同)。toString()方法通常返回带时区信息的日期和时间,而时间也是以 24 小时制(0~23)表示的。PST,即 Pacific Standard Time,太平洋标准时间。toLocaleString()和 toString()可能只对调试有用,不能用于显示。

扫描二维码关注公众号,回复: 13113683 查看本文章

日期格式化方法

Date 类型有几个专门用于格式化日期的方法,它们都会返回字符串:

 toDateString()显示日期中的周几、月、日、年(格式特定于实现);

 toTimeString()显示日期中的时、分、秒和时区(格式特定于实现);

 toLocaleDateString()显示日期中的周几、月、日、年(格式特定于实现和地区);

 toLocaleTimeString()显示日期中的时、分、秒(格式特定于实现和地区);

 toUTCString()显示完整的 UTC 日期(格式特定于实现)。

这些方法的输出与 toLocaleString()和 toString()一样,会因浏览器而异。因此不能用于在用户界面上一致地显示日期。

注意 还有一个方法叫 toGMTString(),这个方法跟 toUTCString()是一样的,目的是为了向后兼容。不过,规范建议新代码使用 toUTCString()。

日期/时间组件方法

Date 类型剩下的方法(见下表)直接涉及取得或设置日期值的特定部分。注意表中“UTC 日期”,指的是没有时区偏移(将日期转换为 GMT)时的日期。

getTime() 返回日期的毫秒表示;与 valueOf()相同

setTime(milliseconds) 设置日期的毫秒表示,从而修改整个日期

getFullYear() 返回 4 位数年(即 2019 而不是 19)

getUTCFullYear() 返回 UTC 日期的 4 位数年

setFullYear(year) 设置日期的年(year 必须是 4 位数)

setUTCFullYear(year) 设置 UTC 日期的年(year 必须是 4 位数)

getMonth() 返回日期的月(0 表示 1 月,11 表示 12 月)

getUTCMonth() 返回 UTC 日期的月(0 表示 1 月,11 表示 12 月)

setMonth(month) 设置日期的月(month 为大于 0 的数值,大于 11 加年)

setUTCMonth(month) 设置 UTC 日期的月(month 为大于 0 的数值,大于 11 加年)

getDate() 返回日期中的日(1~31)

getUTCDate() 返回 UTC 日期中的日(1~31)

setDate(date) 设置日期中的日(如果 date 大于该月天数,则加月)

setUTCDate(date) 设置 UTC 日期中的日(如果 date 大于该月天数,则加月)

getDay() 返回日期中表示周几的数值(0 表示周日,6 表示周六)

getUTCDay() 返回 UTC 日期中表示周几的数值(0 表示周日,6 表示周六)

getHours() 返回日期中的时(0~23)

getUTCHours() 返回 UTC 日期中的时(0~23)

setHours(hours) 设置日期中的时(如果 hours 大于 23,则加日)

setUTCHours(hours) 设置 UTC 日期中的时(如果 hours 大于 23,则加日)

getMinutes() 返回日期中的分(0 ~ 59)

getUTCMinutes() 返回 UTC 日期中的分(0 ~ 59)

setMinutes(minutes) 设置日期中的分(如果 minutes 大于 59,则加时)

setUTCMinutes(minutes) 设置 UTC 日期中的分(如果 minutes 大于 59,则加时)

getSeconds() 返回日期中的秒(0~59)

getUTCSeconds() 返回 UTC 日期中的秒(0~59)

setSeconds(seconds) 设置日期中的秒(如果 seconds 大于 59,则加分)

setUTCSeconds(seconds) 设置 UTC 日期中的秒(如果 seconds 大于 59,则加分)

getMilliseconds() 返回日期中的毫秒

getUTCMilliseconds() 返回 UTC 日期中的毫秒

setMilliseconds(milliseconds) 设置日期中的毫秒

setUTCMilliseconds(milliseconds) 设置 UTC 日期中的毫秒

getTimezoneOffset() 返回以分钟计的 UTC 与本地时区的偏移量(如美国 EST 即“东部标准时间”

返回 300,进入夏令时的地区可能有所差异)

RegExp

ECMAScript 通过 RegExp 类型支持正则表达式。正则表达式使用类似 Perl 的简洁语法来创建:

let expression = /pattern/flags;

这个正则表达式的 pattern(模式)可以是任何简单或复杂的正则表达式,包括字符类、限定符、

分组、向前查找和反向引用。每个正则表达式可以带零个或多个 flags(标记),用于控制正则表达式

的行为。下面给出了表示匹配模式的标记。

 g:全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束。

 i:不区分大小写,表示在查找匹配时忽略 pattern 和字符串的大小写。

 m:多行模式,表示查找到一行文本末尾时会继续查找。

 y:粘附模式,表示只查找从 lastIndex 开始及之后的字符串。

 u:Unicode 模式,启用 Unicode 匹配。

 s:dotAll 模式,表示元字符.匹配任何字符(包括\n 或\r)

与其他语言中的正则表达式类似,所有元字符在模式中也必须转义,包括:( [ { \ ^ $ | ) ] } ? * + .

RegExp 实例属性

每个 RegExp 实例都有下列属性,提供有关模式的各方面信息。

 global:布尔值,表示是否设置了 g 标记。

 ignoreCase:布尔值,表示是否设置了 i 标记。

 unicode:布尔值,表示是否设置了 u 标记。

 sticky:布尔值,表示是否设置了 y 标记。

 lastIndex:整数,表示在源字符串中下一次搜索的开始位置,始终从 0 开始。

 multiline:布尔值,表示是否设置了 m 标记。

 dotAll:布尔值,表示是否设置了 s 标记。

 source:正则表达式的字面量字符串(不是传给构造函数的模式字符串),没有开头和结尾的斜杠。

 flags:正则表达式的标记字符串。始终以字面量而非传入构造函数的字符串模式形式返回(没

有前后斜杠)

source 和 flags 属性返回的是规范化之后可以在字面量中使用的形式

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

如果模式设置了全局标记,则每次调用 exec()方法会返回一个匹配的信息。如果没有设置全局标记,则无论对同一个字符串调用多少次 exec(),也只会返回第一个匹配的信息。

正则表达式的另一个方法是 test(),接收一个字符串参数。如果输入的文本与模式匹配,则参数返回 true,否则返回 false。这个方法适用于只想测试模式是否匹配,而不需要实际匹配内容的情况。test()经常用在 if 语句中。

这里的模式是通过 RegExp 构造函数创建的,但 toLocaleString()和 toString()返回的都是其字面量的形式。注意 正则表达式的 valueOf()方法返回正则表达式本身。

RegExp 构造函数本身也有几个属性。(在其他语言中,这种属性被称为静态属性。)这些属性适用于作用域中的所有正则表达式,而且会根据最后执行的正则表达式操作而变化。每个属性都有一个全名和一个简写。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BgkOr73h-1614079246644)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223164335122.png)]

以上代码创建了一个模式,用于搜索任何后跟"hort"的字符,并把第一个字符放在了捕获组中。不同属性包含的内容如下。

 input 属性中包含原始的字符串。

 leftConext 属性包含原始字符串中"short"之前的内容,rightContext 属性包含"short"之后的内容。

 lastMatch 属性包含匹配整个正则表达式的上一个字符串,即"short"。

 lastParen 属性包含捕获组的上一次匹配,即"s"。

模式包含两个捕获组。调用 test()搜索字符串之后,因为找到了匹配项所以返回true,而且可以打印出通过 RegExp 构造函数的$1 和$2 属性取得的两个捕获组匹配的内容。注意 RegExp 构造函数的所有属性都没有任何 Web 标准出处,因此不要在生产环境中使用它们。

模式局限

正则表达式但仍然缺少 Perl 语言中的一些高级特性。下列特性目前还没有得到 ECMAScript 的支持:

 \A 和\Z 锚(分别匹配字符串的开始和末尾)

 联合及交叉类

 原子组

 x(忽略空格)匹配模式

 条件式匹配

 正则表达式注释

原始值包装类型

ECMAScript 提供了 3 种特殊的引用类型:Boolean、Number 和 String。

这些类型具有本章介绍的其他引用类型一样的特点,但也具有与各自原始类型对应的特殊行为。每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象,从而暴露出操作原始值的各种方法。这种行为可以让原始值拥有对象的行为。引用类型与原始值包装类型的主要区别在于对象的生命周期。在通过 new 实例化引用类型后,得到的实例会在离开作用域时被销毁,而自动创建的原始值包装对象则只存在于访问它的那行代码执行期间。这意味着不能在运行时给原始值添加属性和方法。

let value = "25"; 
let number = Number(value); // 转型函数
console.log(typeof number); // "number" 
let obj = new Number(value); // 构造函数
console.log(typeof obj); // "object"

虽然不推荐显式创建原始值包装类型的实例,但它们对于操作原始值的功能是很重要的。每个原始值包装类型都有相应的一套方法来方便数据操作。

Boolean 是对应布尔值的引用类型。要创建一个 Boolean 对象,就使用 Boolean 构造函数并传入true 或 false,如下例所示:

let booleanObject = new Boolean(true);

Boolean 的实例会重写 valueOf()方法,返回一个原始值 true 或 false。toString()方法被调用时也会被覆盖,返回字符串"true"或"false"。所有对象在布尔表达式中都会自动转换为 true,因此 falseObject 在这个表达式里实际上表示一个 true 值。

原始值和引用值(Boolean 对象)还有几个区别。首先,typeof 操作符对原始值返回"boolean",但对引用值返回"object"。同样,Boolean 对象是 Boolean 类型的实例,在使用instaceof 操作符时返回 true,但对原始值则返回 false。理解原始布尔值和 Boolean 对象之间的区别非常重要,强烈建议永远不要使用后者。

Number 是对应数值的引用类型。要创建一个 Number 对象,就使用 Number 构造函数并传入一个数值,如下例所示:

let numberObject = new Number(10);

与 Boolean 类型一样,Number 类型重写了 valueOf()、toLocaleString()和 toString()方法。valueOf()方法返回 Number 对象表示的原始数值,另外两个方法返回数值字符串。toString()方法可选地接收一个表示基数的参数,并返回相应基数形式的数值字符串。

toFixed()方法返回包含指定小数点位数的数值字符串。toFixed()自动舍入的特点可以用于处理货币。不过要注意的是,多个浮点数值的数学计算不一定得到精确的结果。比如,0.1 + 0.2 = 0.30000000000000004。toFixed()方法可以表示有 0~20 个小数位的数值。

另一个用于格式化数值的方法是 toExponential(),返回以科学记数法(也称为指数记数法)表示的数值字符串。与 toFixed()一样,toExponential()也接收一个参数,表示结果中小数的位数。

toPrecision()方法会根据情况返回最合理的输出结果,可能是固定长度,也可能是科学记数法形式。这个方法接收一个参数,表示结果中数字的总位数(不包含指数)。本质上,toPrecision()方法会根据数值和精度来决定调用 toFixed()还是 toExponential()。为了以正确的小数位精确表示数值,这 3 个方法都会向上或向下舍入。

Number 对象也为数值提供了重要能力。但是,考虑到两者存在同样的潜在问题,因此并不建议直接实例化 Number 对象。在处理原始数值和引用数值时,typeof 和 instacnceof操作符会返回不同的结果

ES6 新增了 Number.isInteger()方法,用于辨别一个数值是否保存为整数。有时候,小数位的 0可能会让人误以为数值是一个浮点值。 console.log(Number.isInteger(1.00)); // true

IEEE 754 数值格式有一个特殊的数值范围,在这个范围内二进制值可以表示一个整数值。这个数值范围从 Number.MIN_SAFE_INTEGER(-2^53+ 1)到 Number.MAX_SAFE_INTEGER(2^53 - 1)。对超出这个范围的数值,即使尝试保存为整数,IEEE 754 编码格式也意味着二进制值可能会表示一个完全不同的数值。为了鉴别整数是否在这个范围内,可以使用 Number.isSafeInteger()方法

String 是对应字符串的引用类型。要创建一个 String 对象,使用 String 构造函数并传入一个数值,如下例所示:

let stringObject = new String(“hello world”);

String 对象的方法可以在所有字符串原始值上调用。3个继承的方法 valueOf()、toLocaleString()和 toString()都返回对象的原始字符串值。

每个 String 对象都有一个 length 属性,表示字符串中字符的数量。String 类型提供了很多方法来解析和操作字符串。

JavaScript 字符串由 16 位码元(code unit)组成。对多数字符来说,每 16 位码元对应一个字符。换句话说,字符串的 length 属性表示字符串包含多少 16 位码元.

charAt()方法返回给定索引位置的字符,由传给方法的整数参数指定。

JavaScript 字符串使用了两种 Unicode 编码混合的策略:UCS-2 和 UTF-16。对于可以采用 16 位编码的字符(U+0000~U+FFFF),这两种编码实际上是一样的。

使用 charCodeAt()方法可以查看指定码元的字符编码。这个方法返回指定索引位置的码元值,索

引以整数指定。

fromCharCode()方法用于根据给定的 UTF-16 码元创建字符串中的字符。这个方法可以接受任意多个数值,并返回将所有数值对应的字符拼接起来的字符串.

这个对应关系在扩展到 Unicode 增补字符平面时就不成立了。问题很简单,即 16 位只能唯一表示65 536 个字符。这对于大多数语言字符集是足够了,在 Unicode 中称为基本多语言平面(BMP)。为了表示更多的字符,Unicode 采用了一个策略,即每个字符使用另外 16 位去选择一个增补平面。这种每个字符使用两个 16 位码元的策略称为代理对。

为正确解析既包含单码元字符又包含代理对字符的字符串,可以使用 codePointAt()来代替charCodeAt()。codePointAt()方法可以从指定码元位置识别完整的码点。 charCodeAt()有对应的 codePointAt()一样,fromCharCode()也有一个对应的 fromCodePoint()。这个方法接收任意数量的码点,返回对应字符拼接起来的字符串

**normalize()**方法

某些 Unicode 字符可以有多种编码方式。有的字符既可以通过一个 BMP 字符表示,也可以通过一个代理对表示。

Unicode提供了 4种规范化形式,可以将类似上面的字符规范化为一致的格式,无论底层字符的代码是什么。这 4种规范化形式是:NFD(Normalization Form D)、NFC(Normalization Form C)、NFKD(Normalization Form KD)和 NFKC(Normalization Form KC)。可以使用 normalize()方法对字符串应用上述规范化形式,使用时需要传入表示哪种形式的字符串:“NFD”、“NFC”、"NFKD"或"NFKC"通过比较字符串与其调用 normalize()的返回值,就可以知道该字符串是否已经规范化了

字符串操作方法

首先是 concat(),用于将一个或多个字符串拼接成一个新字符串。concat()方法可以接收任意多个参数,因此可以一次性拼接多个字符串。

ECMAScript 提供了 3 个从字符串中提取子字符串的方法: slice()、 substr()和 substring()。这
3 个方法都返回调用它们的字符串的一个子字符串,而且都接收一或两个参数。第一个参数表示子字符串开
始的位置,第二个参数表示子字符串结束的位置。对 slice()和 substring()而言,第二个参数是提取结
束的位置(即该位置之前的字符会被提取出来)。对 substr()而言,第二个参数表示返回的子字符串数量。
任何情况下,省略第二个参数都意味着提取到字符串末尾。与 concat()方法一样, slice()、 substr()
和 substring()也不会修改调用它们的字符串,而只会返回提取到的原始新字符串值。 slice()、 substr()和 substring()是以相同方式被调用的,而且多数情况下返回的值也相同。

当某个参数是负值时,这 3 个方法的行为又有不同。

比如, slice()方法将所有负值参数都当成字符串长度加上负参数值。
而 substr()方法将第一个负参数值当成字符串长度加上该值,将第二个负参数值转换为 0。
substring()方法会将所有负参数值都转换为 0。

字符串位置方法

有两个方法用于在字符串中定位子字符串: indexOf()和 lastIndexOf()。这两个方法从字符串中搜索传入的字符串,并返回位置(如果没找到,则返回-1)。两者的区别在于, indexOf()方法从字符串开头开始查找子字符串,而 lastIndexOf()方法从字符串末尾开始查找子字符串。

这两个方法都可以接收可选的第二个参数,表示开始搜索的位置。这意味着, indexOf()会从这个
参数指定的位置开始向字符串末尾搜索,忽略该位置之前的字符; lastIndexOf()则会从这个参数指
定的位置开始向字符串开头搜索,忽略该位置之后直到字符串末尾的字符。

ECMAScript 6 增加了 3 个用于判断字符串中是否包含另一个字符串的方法: startsWith()、endsWith()和 includes()。这些方法都会从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值。它们的区别在于, startsWith()检查开始于索引 0 的匹配项, endsWith()检查开始于索引(string.length -substring.length)的匹配项,而 includes()检查整个字符串。startsWith()和 includes()方法接收可选的第二个参数,表示开始搜索的位置。如果传入第二个参数,则意味着这两个方法会从指定位置向着字符串末尾搜索,忽略该位置之前的所有字符。endsWith()方法接收可选的第二个参数,表示应该当作字符串末尾的位置。如果不提供这个参数,那么默认就是字符串长度。如果提供这个参数,那么就好像字符串只有那么多字符一样。

ECMAScript 在所有字符串上都提供了 trim()方法。这个方法会创建字符串的一个副本,删除前、后所有空格符,再返回结果。 trim()返回的是字符串的副本,因此原始字符串不受影响,即原本的前、后空格符都会保留。另外, trimLeft()和 trimRight()方法分别用于从字符串开始和末尾清理空格符。

ECMAScript 在所有字符串上都提供了 repeat()方法。这个方法接收一个整数参数,表示要将字
符串复制多少次,然后返回拼接所有副本后的结果。

let stringValue = "na ";
console.log(stringValue.repeat(16) + "batman");
// na na na na na na na na na na na na na na na na batman

padStart()和 padEnd()方法会复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件。这两个方法的第一个参数是长度,第二个参数是可选的填充字符串,默认为空格.可选的第二个参数并不限于一个字符。如果提供了多个字符的字符串,则会将其拼接并截断以匹配指定长度。此外,如果长度小于或等于字符串长度,则会返回原始字符串。

字符串的原型上暴露了一个@@iterator 方法,表示可以迭代字符串的每个字符。有了这个迭代器之后,字符串就可以通过解构操作符来解构了。比如,可以更方便地把字符串分割为字符数组

toLowerCase()和toUpperCase()方法是原来就有的方法,与 java.lang.String 中的方法同名。 toLocaleLowerCase()和 toLocaleUpperCase()方法旨在基于特定地区实现。在很多地区,地区特定的方法与通用的方法是一样的。但在少数语言中(如土耳其语),Unicode 大小写转换需应用特殊规则,要使用地区特定的方法才能实现正确转换.通常,如果不知道代码涉及什么语言,则最好使用地区特定的转换方法。

String 类型专门为在字符串中实现模式匹配设计了几个方法。第一个就是 match()方法,这个方
法本质上跟 RegExp 对象的 exec()方法相同。 match()方法接收一个参数,可以是一个正则表达式字
符串,也可以是一个 RegExp 对象。match()方法返回的数组与 RegExp 对象的 exec()方法返回的数组是一样的:第一个元素是与整
个模式匹配的字符串,其余元素则是与表达式中的捕获组匹配的字符串(如果有的话)。
另一个查找模式的字符串方法是 search()。这个方法唯一的参数与 match()方法一样:正则表达
式字符串或 RegExp 对象。这个方法返回模式第一个匹配的位置索引,如果没找到则返回1。 search()
始终从字符串开头向后匹配模式。为简化子字符串替换操作, ECMAScript 提供了 replace()方法。这个方法接收两个参数,第一个
参数可以是一个 RegExp 对象或一个字符串(这个字符串不会转换为正则表达式),第二个参数可以是
一个字符串或一个函数。如果第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字
符串,第一个参数必须为正则表达式并且带全局标记.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rcUe1vJo-1614079246647)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223183534344.png)]

最后一个与模式匹配相关的字符串方法是 split()。这个方法会根据传入的分隔符将字符串拆分成数组。作为分隔符的参数可以是字符串,也可以是 RegExp 对象。(字符串分隔符不会被这个方法当成
正则表达式。)还可以传入第二个参数,即数组大小,确保返回的数组不会超过指定大小。

最后一个方法是 localeCompare(),这个方法比较两个字符串,返回如下 3 个值中的一个。
 如果按照字母表顺序,字符串应该排在字符串参数前头,则返回负值。(通常是-1,具体还要看
与实际值相关的实现。)
 如果字符串与字符串参数相等,则返回 0。
 如果按照字母表顺序,字符串应该排在字符串参数后头,则返回正值。(通常是 1,具体还要看
与实际值相关的实现。)

早期的浏览器开发商认为使用 JavaScript 动态生成 HTML 标签是一个需求。因此,早期浏览器扩展
了规范,增加了辅助生成 HTML 标签的方法。下表总结了这些 HTML 方法。不过,这些方法基本上已
经没有人使用了,因为结果通常不是语义化的标记。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uT0UlPsp-1614079246654)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223183932854.png)]

单例内置对象

ECMA-262 对内置对象的定义是“任何由 ECMAScript 实现提供、与宿主环境无关,并在 ECMAScript
程序开始执行时就存在的对象”。这就意味着,开发者不用显式地实例化内置对象,因为它们已经实例
化好了。前面我们已经接触了大部分内置对象,包括 Object、 Array 和 String。本节介绍 ECMA-262
定义的另外两个单例内置对象: Global 和 Math。

Global 对象是 ECMAScript 中最特别的对象,因为代码不会显式地访问它。ECMA-262 规定 Global
对象为一种兜底对象,它所针对的是不属于任何对象的属性和方法。事实上,不存在全局变量或全局函
数这种东西。在全局作用域中定义的变量和函数都会变成 Global 对象的属性 。本书前面介绍的函数,
包括 isNaN()、 isFinite()、 parseInt()和 parseFloat(),实际上都是 Global 对象的方法。除
了这些, Global 对象上还有另外一些方法。

encodeURI()和 encodeURIComponent()方法用于编码统一资源标识符(URI),以便传给浏览器。
有效的 URI 不能包含某些字符,比如空格。使用 URI 编码方法来编码 URI 可以让浏览器能够理解它们,
同时又以特殊的 UTF-8 编码替换掉所有无效字符。

ecnodeURI()方法用于对整个 URI 进行编码,比如"www.wrox.com/illegal value.js"。而
encodeURIComponent()方法用于编码 URI 中单独的组件. encodeURI()不会编码属于 URL 组件的特殊字符,比如冒号、斜杠、问号、井号,而 encodeURIComponent()会编码它发现的所有非标准字符. 一般来说,使用 encodeURIComponent()应该比使用 encodeURI()的频率更高,
这是因为编码查询字符串参数比编码基准 URI 的次数更多。

URI 方法 encodeURI()、encodeURIComponent()、decodeURI()和 decodeURIComponent()取代了 escape()和 unescape()方法, 后者在 ECMA-262 第 3 版中就已经
废弃了。 URI 方法始终是首选方法,因为它们对所有 Unicode 字符进行编码,而原来的方
法只能正确编码 ASCII 字符。不要在生产环境中使用 escape()和 unescape()。

最后一个方法可能是整个 ECMAScript 语言中最强大的了,它就是 eval()。这个方法就是一个完
整的 ECMAScript 解释器,它接收一个参数,即一个要执行的 ECMAScript(JavaScript)字符串。当解释器发现 eval()调用时,会将参数解释为实际的 ECMAScript 语句,然后将其插入到该位置。
通过 eval()执行的代码属于该调用所在上下文,被执行的代码与该上下文拥有相同的作用域链。这意
味着定义在包含上下文中的变量可以在 eval()调用内部被引用,通过 eval()定义的任何变量和函数都不会被提升,这是因为在解析代码的时候,它们是被包含在
一个字符串中的。它们只是在 eval()执行的时候才会被创建。
在严格模式下,在 eval()内部创建的变量和函数无法被外部访问。换句话说,最后两个例子会报
错。同样,在严格模式下,赋值给 eval 也会导致错误

*解释代码字符串的能力是非常强大的,但也非常危险。在使用 eval()的时候必须
极为慎重,特别是在解释用户输入的内容时。因为这个方法会对 XSS 利用暴露出很大的
攻击面。恶意用户可能插入会导致你网站或应用崩溃的代码。

Global 对象属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CwqWPgk9-1614079246665)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223191156464.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vWhuxOsm-1614079246672)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223191221640.png)]

虽然 ECMA-262 没有规定直接访问 Global 对象的方式,但浏览器将 window 对象实现为 Global
对象的代理。因此,所有全局作用域中声明的变量和函数都变成了 window 的属性

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-naP4whh0-1614079246677)(C:%5CUsers%5C34557%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210223191419681.png)]

min()和 max()方法用于确定一组数值中的最小值和最大值。这两个方法都接收任意多个参数

把小数值舍入为整数的 4 个方法: Math.ceil()、 Math.floor()、 Math.round()
和 Math.fround()。这几个方法处理舍入的方式如下所述。
 Math.ceil()方法始终向上舍入为最接近的整数。

 Math.floor()方法始终向下舍入为最接近的整数。
 Math.round()方法执行四舍五入。
 Math.fround()方法返回数值最接近的单精度(32 位)浮点值表示。

Math.random()方法返回一个 0~1 范围内的随机数,其中包含 0 但不包含 1。Math.random()方法在这里出于演示目的是没有问题的。如果是为了加密而需要生成随机数(传给生成器的输入需要较高的不确定性),那么建议使用 window.crypto.getRandomValues()。

其他方法

小结
JavaScript 中的对象称为引用值,几种内置的引用类型可用于创建特定类型的对象。
 引用值与传统面向对象编程语言中的类相似,但实现不同。
 Date 类型提供关于日期和时间的信息,包括当前日期、时间及相关计算。
 RegExp 类型是 ECMAScript 支持正则表达式的接口,提供了大多数基础的和部分高级的正则表
达式功能。
JavaScript 比较独特的一点是,函数实际上是 Function 类型的实例,也就是说函数也是对象。因
为函数也是对象,所以函数也有方法,可以用于增强其能力。
由于原始值包装类型的存在, JavaScript 中的原始值可以被当成对象来使用。有 3 种原始值包装类
型: Boolean、 Number 和 String。它们都具备如下特点。
 每种包装类型都映射到同名的原始类型。
 以读模式访问原始值时,后台会实例化一个原始值包装类型的对象,借助这个对象可以操作相
应的数据。
 涉及原始值的语句执行完毕后,包装对象就会被销毁。
当代码开始执行时,全局上下文中会存在两个内置对象: Global 和 Math。其中, Global 对象在
大多数 ECMAScript 实现中无法直接访问。不过,浏览器将其实现为 window 对象。所有全局变量和函
数都是 Global 对象的属性。 Math 对象包含辅助完成复杂计算的属性和方法。

猜你喜欢

转载自blog.csdn.net/weixin_40599109/article/details/114001255