内容均摘自JavaScript高级程序设计第四版,仅用于记录学习过程。
一. 理解引用类型
5.1 理解引用类型
引用值 (或对象 )是某个特定的引用类型 的实例
- 在ECMAScript 中,
引用类型 是把数据和功能组织到一起的结构 - 常被人
错误 地称"类 " 引用类型 有时也被称为对象定义 ,因为它们描述了自己的对象应有的属性和方法
新对象通过使用new 操作符后跟一个构造函数 来创建,构造函数 就是用来创建新对象 的函数,比如下面这行代码:
let now = new Date();
- 创建了引用类型
Date 的一个新实例,并将它保存在变量now 中 Date() 是构造函数,负责创建一个只有默认属性和方法的简单对象
二. Date
5.2 Date
Date 类型将日期保存为1970年1月1日零时 至今所经过的毫秒数
创建日期对象,使用new 操作符来调用Date 构造函数:
let now = new Date();
- 不给
Date 构造函数传参数的情况下,创建的对象将保存当前 日期和时间 - 若要基于其他日期和时间创建日期对象,必须传入其毫秒表示,ECMAScript 为此提供了两个辅助方法:
Date.parse() 和 Date.UTC()
Date.parse()
Date.parse() :接收一个表示日期的字符串参数 ,尝试将这个字符串转换为表示该日期的毫秒数
- 支持的日期格式:
- “月/日/年”,如"5/23/2021"
- “月名 日,年”,如"May 23,2021"
- “周几 月名 日 年 时:分:秒 时区”,如"Tue May 23 2021 00:00:00 GMT-0700"
若直接把表示日期的字符串传给Date() ,Date 会在后台调用Date.parse()
比如,要创建一个表示"2021年5月23日"的日期对象,可以使用以下代码:
let date = new Date(Date.parse("5/23/2021"));
let date = new Date("5/23/2021");
??:若传的字符串不表示日期,则Date.parse() 返回NaN
Date.UTC()
Date.UTC() 也是返回日期的毫秒数
- 参数:年、月(以0为起点)、日(1~31)、时(0~23)、分、秒、毫秒
(只有年和月是必需的,日不提供则默认为1,其他不提供则默认为0)
Date.UTC() 也会被Date() 隐式调用,但隐式调用下创建的是本地日期 ,不是GMT日期
下面是两个例子:
let date = new Date(Date.UTC(2000, 0));
let date = new Date(2000, 0);
let date = new Date(Date.UTC(2021, 7, 1, 5, 55, 55));
Date.now()
返回表示方法执行时 的日期和时间的毫秒数 这个方法可以用在代码分析中:
let start = Date.now();
doSomething();
let stop = Date.now();
result = stop - start;
5.2.1 继承的方法
与其他引用类型一样,Date 重写了toLocaleString() 、toString() 、valueOf() 方法
toLocaleString() :返回与浏览器运行的本地环境 一致的日期和时间,格式中包含AM(上午) 或 PM(下午) ,但不包含时区信息,具体格式可能因浏览器而不同toString() :返回带时区信息 的日期和时间
下面给出这两种方法返回的示例: 2021年8月2日零点
8/2/2021 12:00:00 AM
Mon Aug 2 2021 00:00:00 GMT-0800 (Pacific Standard Time)
let date1 = new Date(2021, 0, 1);
let date2 = new Date(2021, 1, 1);
console.log(date1 < date2);
5.2.2 日期格式化方法
toDateString() :显示日期中的周几、月、日、年(格式特定于实现)toTimeString() :显示日期中的时、分、秒、时区(格式特定于实现)toLocalDateString() :显示日期中的周几、月、日、年(格式特定于实现和地区)toLocaleTimeString() :显示时期中的时、分、秒(格式特定于实现和地区)toUTCString() :显示完整的UTC日期(格式特定于实现)
这些方法的输出会因浏览器而异,因此不能用于在用户界面上一致地显示日期。
5.2.3 日期/时间组件方法
Date 引用类型的其他方法涉及取得 或设置 日期值的特定部分 ??:UTC日期 指的是没有时区偏移(将日期转换为GMT)时的日期  
三. RegExp
5.3 RegExp
ECMAScript 通过 RegExp 类型支持正则表达式 正则表达式的创建:
let expression = /pattern/flags;
pattern (模式)可以是任何正则表达式,包括字符类、限定符、分组、向前查找、反向引用 每个正则表达式可以不带或带多个flags (标记),用于控制正则表达式的行为
匹配模式的标记:
g :全局模式,查找字符串的全部 内容,而不是找到第一个匹配的内容就结束I :不区分大小写,查找匹配时忽略大小写m :多行模式,查找到一行文本末尾时会继续查找y :粘附模式,只查找从lastIndex 开始及之后的字符串u :Unicode模式,启用 Unicode 匹配s :dotAll模式,匹配任何字符,包括\n 或\r
let p1 = /at/g;
let p2 = /[bc]at/i;
元字符在模式中必须转义,因为元字符在正则表达式中都有多种特殊功能,所以要匹配这些字符本身就必须使用反斜杠 来转义 包括:
() [] {} \ ^ $ | ? * + .
let p1 = /\[bc\]at/i;
let p2 = /\.at/gi;
上面例子中的正则表达式都是使用字面量形式定义的 也可以使用 RegExp 构造函数来创建
let p = /[bc]at/i;
let p = new RegExp("[bc]at", "i");
- 因为
RegExp 引用类型的模式参数是字符串,所以在某些情况下需要二次转义  - 使用
RegExp 也可以基于已有的正则表达式实例,并可选择性地修改它们的标记:
const r1 = /cat/g;
const r2 = new RegExp(r1);
const r3 = new RegExp(r1, "i");
console.log(r2);
console.log(r3);
5.3.1 RegExp实例属性
每个 RegExp 实例都有下列属性:
global :布尔值,是否设置了g 标记ignoreCase :布尔值,是否设置了i 标记unicode :布尔值,是否设置了u 标记sticky :布尔值,是否设置了y 标记multiline :布尔值,是否设置了m 标记dotAll :布尔值,是否设置了s 标记lastIndex :整数,在源字符串中下一次搜索的开始位置source :正则表达式的字面量字符串,没有开头和结尾的斜杠flags :正则表达式的标记字符串
通过这些属性可以全面了解正则表达式的信息,不过实际开发中用的不多
5.3.2 RegExp 实例方法
exec()
RegExp 实例的主要方法是exec() ,主要用于配合捕获组 使用
- 只接收一个参数,要作为
模式 的字符串 - 如果找到了匹配项,返回包含第一个匹配信息的数组
- 如果没找到匹配项,返回
null
返回的数组是Array 的实例,包含两个额外的属性:index 和input
index 是字符串中匹配模式字符串 的第一个字符的位置input 是要被查找的字符串
数组的第一个元素是匹配整个模式 的字符串,其他元素是与表达式 中的捕获组 匹配的字符串 下例:
let text = "mom and dad and baby";
let pattern = /mom( and dad( and baby)?)?/gi;
let matches = pattern.exec(text);
console.log(matches.index);
console.log(matches.input);
console.log(matches[0]);
console.log(matches[1]);
console.log(matches[2]);
这个例子中,模式 包含两个捕获组 :
- 最内部的匹配项
" and baby" - 外部的匹配项
" and dad" 或 " and dad and baby"
数组的第一个元素是匹配的整个字符串 ,第二个元素是匹配第一个捕获组 的字符串,第三个元素是匹配第二个捕获组 的字符串。
全局标记
如果模式设置了全局标记 ,则每一次调用exex() 都会返回一个匹配的信息,若不设置全局标记 ,无论调用多少次exex() ,也只会返回第一个匹配的信息
看下例:
let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = pattern.exec(text);
console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
matches = pattern.exec(text);
console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
上面例中的模式没有设置全局标记 ,因此调用exex() 只会返回第一个匹配项("cat" ) ??:lastIndex 在非全局模式下始终不变 (lastIndex 表示在查找字符串中下一次搜索开始的位置)
如果在这个模式上设置了g 标记,则每次调用exec() 都会在字符串中向前搜索下一个匹配项
看下例:
let text = "cat, bat, sat, fat";
let pattern = /.at/g;
let matches = pattern.exec(text);
console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
matches = pattern.exec(text); console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
...
这次模式设置了全局标记 ,因此每次调用 exec() 都会返回字符串中的下一个匹配项 ,直到搜索到 字符串末尾 ??:lastIndex 在全局模式下每次调用exec() 都会更新 (lastIndex 表示在查找字符串中下一次搜索开始的位置)
粘附标记
如果模式设置了粘附标记 y ,则每次调用exec() 就只会在 lastIndex 的位置上寻找匹配项,不会跳过往后查找 粘附标记覆盖全局标记
let text = "cat, bat, sat, fat";
let pattern = /.at/y;
let matches = pattern.exec(text);
console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
matches = pattern.exec(text);
console.log(matches);
console.log(pattern.lastIndex);
pattern.lastIndex = 5;
matches = pattern.exec(text);
console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
test()
正则表达式的另一个方法是test()
- 接收一个字符串参数
- 如果输入的
文本 与模式 匹配,则返回true ,否则返回false
test() 常用于if 语句中:
let text = "000-00-0000";
let pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)) {
console.log("The pattern was matched.");
}
上面的例子中,正则表达式用于测试特定的序列 这个用法常用于验证用户输入 ,此时我们只在乎输入是否有效,不关心为什么无效
??: 无论正则表达式是怎么创建的,toLocaleString() 和 toString() 都返回正则表达式的字面量表示 ,valueOf() 方法返回正则表达式本身 比如:
let pattern = new RegExp("\\[bc\\]at", "gi");
console.log(pattern.toString());
console.log(pattern.toLocaleString());
console.log(pattern.valueOf());

5.3.3 RegExp构造函数属性
RegExp构造函数 本身也有几个属性(在其他语言中,这种属性被称为静态属性 ) 这些属性适用于作用域中的所有正则表达式 并且这些属性可以通过两种不同的方式访问(全名和简写) 
四. 原始值包装类型
5.4 原始值包装类型
ECMAScript 提供了 3 种特殊的引用类型: Boolean 、Number 、String 这些类型具有本章介绍的其他引用类型一样的特点,也具有与各自原始类型对应的特殊行为
每当用到某个原始值 的方法和属性 时,后台都会创建 一个相应 的原始包装类型 的对象 ,从而暴露 出操作原始值 的各种方法
let s1 = "some text";
let s2 = s1.substring(2);
变量s1 包含一个字符串,它是一个原始值 第二行在变量s1 上调用了substring() 方法,把结果保存在变量s2 中
我们知道,原始值本身不是对象,逻辑上不应该有方法,这是因为后台进行了很多处理,从而实现上述操作。
- 具体来说,当第二行访问变量
s1 时,是以读模式 访问的,也就是要从内存中读取 变量s1 保存的值 - 在以
读模式 访问字符串的时候,后台都会执行以下3步:
- 创建一个
String 类型的实例 - 调用
实例 上的特定方法 销毁 实例
let s1 = new String("some text");
let s2 = s1.substring(2);
s1 = null;
这种行为可以让原始值拥有对象的行为
引用类型与原始值包装类型的主要区别在于对象 的生命周期
可以显式地使用Boolean 、Number 、String 构造函数创建原始值包装对象,确定是必要时再这么做,否则容易让开发者分不清到底它们是原始值还是引用值
Object 构造函数作为一个工厂方法 ,可以根据传入值 的类型返回相应原始值包装类型 的实例
let obj1 = new Object("some text");
console.log(obj1 instanceof String);
let obj2 = new Object(1);
console.log(obj2 instanceof Number);
let obj3 = new Object(true);
console.log(obj3 instanceof Boolean);
??:使用new 调用原始包装类型的构造函数,与调用同名的转型函数并不一样
let value = "25";
let num1 = Number(value);
console.log(typeof num1);
let num2 = new Number(value);
console.log(typeof num2);
在本例中,变量num1 保存的是一个值为25的原始数值,而变量num2 保存的是一个Number 的实例
不推荐显式 创建原始值包装类型 的实例 ,虽然它们对于操作原始值的功能很重要
5.4.1 Boolean
Boolean 是布尔值的引用类型 要创建一个Boolean对象 ,使用Boolean() ,并传入 true 或 false ,如下例所示:
let booleanObj = new Boolean(true);
在布尔表达式中使用Boolean对象
Boolean 对象在布尔表达式 中使用时容易引起误会,用得很少:
let falseObj = new Boolean(false);
let result = falseObj && true;
console.log(result);
let falseVal = false;
result = falseVal && true;
console.log(result);
在本例中,第2行对falseObj 和true 进行布尔运算,但这个运算是对falseObj 对象,而不是对它表示的值false 求值,这里就要??:所有对象在布尔表达式中都会自动转换为true 所以true && true 当然也为true
原始布尔值和布尔对象的区别
原始值和引用值(Boolean对象 )还有一些区别:
typeof 操作符对原始值返回"boolean" ,对引用值返回object instanceof 操作符对原始值返回false ,对引用值返回true
console.log(falseObj instanceof Boolean);
console.log(falseVal instanceof Boolean);
理解原始布尔值 和Boolean对象 的区别很重要 强烈建议永远不要使用Boolean对象
5.4.2 Number
Number 是数值的引用类型 要创建一个Number对象 ,使用Number() ,并传入 一个数值,如下例所示:
let numberObj = new Number(10);
Number 引用类型重写了valueOf() 、toLocaleString() 、toString()
valueOf() 返回Number 对象表示的原始数值 toLocaleString() 、toString() 返回数值字符串toString() 可以接收一个表示基数的参数
let num = 10;
console.log(num.toString());
console.log(num.toString(2));
console.log(num.toString(16));
将数值格式化为字符串的方法
toFixed() :返回包含指定小数点位数 的数值字符串,此方法会自动四舍五入
let num = 10;
console.log(num.toFixed(2));
toExponential() :返回以科学计数法 表示的数值字符串
let num = 10;
console.log(num.toExponential(1));
console.log(num.toExponential(3));
toPrecision() :根据情况返回最合理的输出结果,接收一个 参数,表示结果中数字的总位数 (不包含指数)
let num = 99;
console.log(num.toPrecision(1));
console.log(num.toPrecision(2));
console.log(num.toPrecision(3));
在本例中,第二行:要用1位数字表示99 ,99 不能只用1位数字来精确表示,所以这个方法将它舍入为100 本质上,toPrecision() 方法会根据数值 和精度 来决定调用 toFixed() 还是 toExponential()
原始数值和数值对象的区别
typeof 操作符对原始值返回"number" ,对引用值返回object instanceof 操作符对原始值返回false ,对引用值返回true
let numObj = new Number(10);
let numVal = 10;
console.log(numObj instanceof Number);
console.log(numVal instanceof Number);
理解原始数值 和Number对象 的区别很重要 同样建议不要使用Number对象
isInteger()方法与安全整数
ES6新增了Number.isInteger() 方法,用于辨别一个数值是否保存为整数
console.log(Number.isInteger(1));
console.log(Number.isInteger(1.00));
在Number.MIN_SAFE_INTERGER (-253 + 1)到Number.MAX_SAFE_INTERGER (253 - 1)范围内,二进制 值可以表示为一个整数 值 超出此范围的数值,即使尝试保存为整数,IEEE 754 编码格式也意味着二进制值可能会表示一个完全不同的数值 可以使用Number.isSageInteger() 鉴别整数是否在这个范围内
console.log(Number.isSafeInteger(-1 * (2 ** 53)));
console.log(Number.isSafeInteger(-1 * (2 ** 53) + 1));
5.4.3 String
String 是字符串的引用类型 要创建一个String对象 ,使用String() ,并传入 一个字符串,如下例所示:
let stringObj = new String("hello world");
String对象 的方法可以在所有的字符串原始值 上调用,3个继承的方法valueOf() 、toLocaleString() 、toString() 都返回对象的原始字符串值
length 属性表示字符串中字符的数量 ,需要??:即使字符串中包含双字节字符,也仍然会按单字符来计数
String 类型提供了很多方法来解析和操作字符串:
JavaScript 字符
字符串 由16位码元 组成,对多数字符来说,每16位 码元对应1个 字符。
- 也就是说
length 属性表示字符串 包含多少16位码元 :
let message = "abc";
console.log(message.length);
charAt() 方法返回给定索引位置 的字符,具体来说,这个方法查找指定索引位置的16位码元,并返回该码元对应的字符:
let message = "abc";
console.log(message.charAt(2));
拼接字符串方法 concat()
concat() :用于将一个或多个字符串 拼接成一个新字符串
let stringVal = "hello ";
let result = stringVal.concat("world");
console.log(result);
console.log(stringValue);
??:stringVal 的值是不变的 concat() 也可以接收任意多个参数,可以一次性拼接多个字符串:
let stringVal = "hello ";
let result = stringVal.concat("world","!","hahaha");
console.log(result);
(但更常用的还是+ 拼接多个字符串)
提取子字符串的方法 slice()、substr()、substring()
slice() 、substr() 、substring() 都会返回调用它们的字符串的一个子字符串 ,都接收1或2个参数,都不会修改原字符串
第一个参数 :表示子字符串开始 的位置第二个参数 :
- 对
slice() 和substring() 而言,表示提取结束的位置(该位置之前的字符会被提取) - 对
substr() 而言,表示提取的子字符串的长度
(若省略第二个参数,默认提取到字符串末尾) ??:接收两个参数时,以较小的那个参数作为起点,较大的参数作为终点
let stringVal = "hello world";
console.log(stringVal.slice(3));
console.log(stringVal.slice(3,7));
console.log(stringVal.substring(3,7));
console.log(stringVal.substr(3,7));
当某个参数 为负数 时:
slice() :将所有负数 参数都当成字符串长度+负数值
let stringVal = "hello world";
console.log(stringVal.slice(-3));
console.log(stringVal.slice(3, -4));
let stringVal = "hello world";
console.log(stringVal.substring(-3));
console.log(stringVal.substring(3, -4));
substr() :将第一 个负参数值当成字符串长度+此值 ,第二 个负参数值当成0
let stringVal = "hello world";
console.log(stringVal.substr(-3));
console.log(stringVal.substr(3, -4));
定位子字符串位置的方法 indexOf() 、lastIndexOf()
indexOf() 和 lastIndexOf() 从字符串中搜索传入的字符串 ,并返回位置 (如果没找到 ,则返回-1 ) 区别在于:
indexOf() 从字符串开头 开始查找子字符串 lastIndexOf() 从字符串末尾 开始查找子字符串
let stringVal = "hello world";
console.log(stringVal.indexOf("o"));
console.log(stringVal.lastIndexOf("o"));
indexOf() 和 lastIndexOf() 都接收可选的第二个参数 ,表示开始搜索 的位置 像这样使用第二个参数并循环调用 indexOf() 或 lastIndexOf() ,可以在字符串中找到所有的目标子字符串,如下所示:
let stringVal = "Pain makes us stronger";
let positions = [];
let pos = stringVal.indexOf("s");
while(pos != -1) {
positions.push(pos);
pos = stringVal.indexOf("s", pos+1);
}
console.log(positions);
本例中,首先取得第一个 "s" 的位置,然后进入循环,将上一次的位置+1 再传给indexOf() 将每一个"s" 的位置都保存在positions 数组中
包含字符串的方法 startsWith()、endsWith()、includes()
ES6新增了3个用于判断字符串中是否包含另一个字符串的方法: 这些方法都会从字符串中搜索 传入的字符串,并返回 一个表示是否包含 的布尔值 区别在于:
startsWith() :检查开始于索引0 的匹配项endsWith() :检查开始于索引string.length - substring.length 的匹配项includes() :检查整个 字符串
let message = "foobarbaz";
console.log(message.startsWith("foo"));
console.log(message.startsWith("bar"));
console.log(message.endsWith("baz"));
console.log(message.endsWith("bar"));
console.log(message.includes("bar"));
console.log(message.includes("qux"));
startsWith() 、includes() 接收可选的第二个参数,表示开始搜索的位置,这两方法会从指定位置向字符串末尾搜索,忽略该位置前的所有字符endsWith() 接收可选的第二个参数,表示应该当作字符串末尾的位置
let message = "foobarbaz";
console.log(message.endsWith("bar", 6));
trim() 方法
trim() 方法会创建字符串的一个副本,删除 前后所有空格符 ,再返回结果
let stringVal = " hello world ";
let trimmedStringVal = stringVal.trim();
console.log(stringVal);
console.log(trimmedStringVal);
还有trimLeft() :从字符串开始 清理空格符 trimRight() :从字符串末尾 清理空格符
repeat() 方法
repeat() 接收一个整数参数 ,表示要将字符串复制 多少次,然后返回拼接所有副本 后的结果
let stringVal = "ha ";
console.log(stringVal.repeat(5));
padStart() 和 padEnd() 方法
padStart() 和 padEnd() 会复制 字符串,如果小于 指定长度,则在相应一边 填充字符,直至满足长度 条件 这两个方法接收两个参数
- 第一个参数是
长度 - 第二个参数是可选的
填充字符 ,默认为空格
let stringVal = "foo";
console.log(stringVal.padStart(6));
console.log(stringVal.padStart(9,"!"));
console.log(stringVal.padEnd(9,"!"));
第二个参数并不限于一个字符 ,可提供多个字符的字符串,则会将其拼接 并截断 以匹配指定长度 如果长度小于 或等于 字符串长度,则会返回原始字符串
let stringVal = "foo";
console.log(stringVal.padStart(8, "bar"));
console.log(stringVal.padStart(2));
字符串迭代与解构
字符串的原型上暴露了一个@@iterator 方法,表示可以迭代 字符串的每个字符 可以像下面这样手动 使用迭代器 :
let message = "abc";
let stringIterator = message[Symbol.iterator]();
console.log(stringIterator.next());
console.log(stringIterator.next());
console.log(stringIterator.next());
console.log(stringIterator.next());
在 for-of 循环中可以通过这个迭代器 访问每个字符:
for (const letter of "abc") {
console.log(letter);
}
有了这个迭代器之后,字符串就可以通过解构操作符 来解构了,比如更方便地把字符串 分割为字符数组 :
let message = "abc";
console.log([...message]);
字符串大小写转换
toLowerCase() toLocaleLowerCase() toUpperCase() toLocaleUpperCase()
let stringValue = "hello world";
console.log(stringValue.toLocaleUpperCase());
console.log(stringValue.toUpperCase());
console.log(stringValue.toLocaleLowerCase());
console.log(stringValue.toLowerCase());
toLocaleLowerCase() 和 toLocaleUpperCase() 方法旨在基于特定地区实现 在很多地区,地区特定的方法与通用的方法是一样的。但在少数语言中(如土耳其语),要使用地区特定的方法才能实现正确转换
字符串模式匹配方法
String 类型为在字符串中实现模式匹配 提供了几个方法
match() :本质上跟RegExp 对象的exec() 方法相同
match() 方法接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp 对象
let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = text.match(pattern); console.log(matches.index);
console.log(matches[0]);
console.log(pattern.lastIndex);
match() 返回的数组 与exec() 返回的数组是一样的:第一 个元素是与整个模式匹配 的字符串 ,其余元素则是与表达式中的捕获组 匹配的字符串(如果有的话)
search() :接收唯一的参数,可以是一个正则表达式字符串,也可以是一个RegExp 对象
- 返回模式第一个匹配的
位置索引 ,没找到返回-1 search() 始终从字符串开头 向后匹配模式
let text = "cat, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos);
replace()
为简化子字符串替换 操作,ECMAScript 提供了 replace() 方法
- 接收两个参数
- 第一个参数可以是一个
RegExp 对象 或一个字符串 (这个字符串不会转换为正则表达式) - 第二个参数可以是
一个字符串 或一个函数
let text = "cat, bat, sat, fat";
let result = text.replace("at", "ond");
console.log(result);
如果第一 个参数是字符串 ,那只会替换第一个子字符串 要想替换所有子字符串 ,第一 个参数必须为正则表达式 并且带全局标记
let text = "cat, bat, sat, fat";
let result = text.replace(/at/g, "ond");
console.log(result);
split()
最后一个与模式匹配相关的字符串方法是 split() 这个方法会根据传入的分隔符 将字符串拆 分成数组
- 接收两个参数
- 第一个参数作为
分隔符 ,可以是字符串 ,也可以是RegExp 对象 - 第二个可选参数是
数组的大小 ,确保返回的数组不会超过指定大小
let colorTxt = "red, blue, green";
let color1 = colorTxt.split(",");
let color2 = colorTxt.split(",", 2);
localeCompare()
localeCompare() 比较两个字符串,返回如下3个值中的一个
- 如果按照字母表顺序,
字符串 应该排在字符串参数前面 ,则返回负值 (通常是-1) - 如果字符串与字符串参数相等,则返回
0 - 如果按照字母表顺序,
字符串 应该排在字符串参数后面 ,则返回正值 (通常是1)
let stringValue = "yellow";
console.log(stringValue.localeCompare("brick"));
console.log(stringValue.localeCompare("yellow"));
console.log(stringValue.localeCompare("zoo"));
"brick" 按字母表顺序应该排在"yellow"前头,因此localeCompare() 返回 1
五. 单例内置对象
5.5 单例内置对象
ECMA-262 对内置对象的定义是: “任何由 ECMAScript 实现提供、与宿主环境无关,并在 ECMAScript 程序开始执行时 就存在 的对象” 这意味着:开发者不用显式地实例化内置对象,因为它们已经实例化好了
前面我们已经解除了大部分内置对象,包括Object 、Array 、String 这里要介绍另外两个单例内置对象:Global 、Math
5.5.1 Global
Global 对象最特别,因为代码不会显式 地访问它 在全局作用域 中定义的变量和函数都会变成Global 对象的属性,前面介绍的函数包括isNaN() 、isFinite() 、parseInt() 等,实际上都是Global 对象的方法
Global 对象上还有一些其他方法:
URL编码方法
encodeURI() 、encodeURIComponent() 用于编码统一资源标识符 (URI),以传给浏览器
有效的URI 不能包含某些字符,比如空格
encodeURI() :对整个URI 进行编码,比如"www.wrox.com/illegal value.js" encodeURIComponent() :对URI 中单独的组件 进行编码,比如前面URL中的"illegal value.js"
区别在于:
encodeURI() 不会编码属于URL 组件的特殊字符 ,比如冒号 、斜杠 、问号 、并号 encodeURIComponent() 会编码它发现的所有非标准字符
let uri = "http://www.wrox.com/illegal value.js#start";
console.log(encodeURI(uri));
console.log(encodeURIComponent(uri));
本例中,使用encodeURI() 编码,只有空格被替换为%20 ,而使用encodeURIComponent() 编码,所有非字母字符 都替换成了相应的编码形式
与 encodeURI() 和 encodeURIComponent() 相对的是 decodeURI() 和 decodeURIComponent()
decodeURI() 只对使用 encodeURI() 编码过的字符解码decodeURIComponent() 解码所有被 encodeURIComponent() 编码的字符,基本上就是解码所有特殊值
eval()
eval() 是一个完整的ECMAScript 解释器 接收一个参数,即要执行的JavaScript字符串
eval("console.log('hi')");
console.log('hi');
当解释器 发现 eval() 调用时,会将参数解释为实际的 ECMAScript 语句 ,然后将其插入 到该位置
Global 对象属性
 
获取Global对象
- 通过
window 对象, 浏览器将window 对象实现为Global 对象的代理 ,因此所有全局作用域 中声明的变量和函数都变成了window 的属性 - 另一种获取
Global 对象的方式:
let global = function() {
return this;
}();
这段代码创建了一个立即调用的函数,返回了this 的值 当一个函数在没有明确成为某个对象的方法 ,或通过call() / apply() 指定this值 的情况下执行的时候,this 值就是Global 对象
5.5.2 Math
Math对象的属性

min() 和 max()
min() 和 max() 用于确定一组数值中的最小值 和最大值 接收任意多个参数
let max = Math.max(3, 54, 32, 16);
console.log(max);
let min = Math.min(3, 54, 32, 16);
console.log(min);
要知道数组 中的最大值和最小值 ,可以像下面这样使用扩展操作符 :
let values = [1, 2, 3, 4, 5, 6, 7, 8];
let max = Math.max(...val);
舍入方法
把小数值舍入为整数:
Math.ceil() :始终向上 舍入为最接近 的整数 Math.floor() :始终向下 舍入为最接近 的整数 Math.round() :四舍五入Math.fround() :返回数值最接近的单精度(32 位)浮点值表示
random() 方法
Math.random() 方法返回一个0~1 范围内的随机数 ,包含0但不包含1
可以基于如下公式使用 Math.random() 从一组整数中随机选择 一个数:
number = Math.floor(Math.random() * totalNumber + minVal)
totalNumber 为可选的总数,minVal 为最小的可能值 这里使用了 Math.floor() 方法,因为 Math.random() 始终返回小数
因此,如果想从1~10 范围内随机选择一个数: 可选的总数有10个值,最小的可能值为1
let num = Math.floor(Math.random() * 10 + 1);
其他方法

六. 小结
js中的对象 称为引用值 ,几种内置的引用类型 可用于创建特定类型 的对象
引用类型 与类 相似,但实现不同Date 引用类型提供关于日期和时间的信息RegExp 引用类型是支持正则表达式的接口
js比较独特的一点是:函数实际上是 Function 类型的实例 ,也就是说函数也是对象。因 为函数也是对象,所以函数也有方法,可以用于增强其能力。
由于原始值包装类型 ,js中的原始值 可以被当成对象 使用,有3种原始值包装类型
Boolean 、Number 、String - 每种包装类型都映射到同名的原始类型
- 以
读模式 访问原始值 时,后台会实例化 一个原始值包装类型 的对象,借助这个对象可以操作响应的数据 - 涉及原始值的语句执行完毕后,包装对象就会被
销毁
当代码开始执行时,全局上下文 中会存在两个内置对象: Global 和 Math
Global 对象无法直接访问,但浏览器将其实现为window 对象,所有全局变量和函数都是Global 对象的属性
|