2024-12-20 日报 Day41

2024-12-20 日报 Day41

Yuyang 前端小白🥬

今日的鸡汤

不是因为看见了成功才坚持,是只有坚持才会看见成功。

今日学习内容

1、JS红皮书P112-114 第五章:基本引用类型

今日笔记

1、RegExp构造函数属性:RegExp 构造函数本身也有几个属性。(在其他语言中,这种属性被称为静态属性。)这些属性适用于作用域中的所有正则表达式,而且会根据最后执行的正则表达式操作而变化。这些属性还有一个特点,就是可以通过两种不同的方式访问它们。换句话说,每个属性都有一个全名和一个简写。下表列出了RegExp 构造函数的属性。
|全名|简写|说明|
|input|$_|最后搜索的字符串(非标准特性)|
|lastMatch|$&|最后匹配的文本|
|lastParen|$+|最后匹配的捕获组(非标准特性)|
|leftContext|$`|input 字符串中 lastMatch 之前的文本。|
|rightContext|$’|input 字符串中 lastMatch 之后的文本。|
这些属性在正则表达式操作期间可能会变化,因此在使用它们时要小心。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
通过这些属性可以提取出与 exec()和 test()执行的操作相关的信息。来看下面的例子:
let text = "this has been a short summer";
let pattern = /(.)hort/g;
if (pattern.test(text)) {
console.log(RegExp.input); // this has been a short summer
console.log(RegExp.leftContext); // this has been a
console.log(RegExp.rightContext); // summer
console.log(RegExp.lastMatch); // short
console.log(RegExp.lastParen); // s
}

这些属性名也可以替换成简写形式,只不过要使用中括号语法来访问,如下面的例子所示,因为大
多数简写形式都不是合法的 ECMAScript 标识符:

1
2
3
4
5
6
7
8
9
10
11
12
13
let text = "this has been a short summer"; 
let pattern = /(.)hort/g;
/*
* 注意:Opera 不支持简写属性名
* IE 不支持多行匹配
*/
if (pattern.test(text)) {
console.log(RegExp.$_); // this has been a short summer
console.log(RegExp["$`"]); // this has been a
console.log(RegExp["$'"]); // summer
console.log(RegExp["$&"]); // short
console.log(RegExp["$+"]); // s
}

RegExp 还有其他几个构造函数属性,可以存储最多 9 个捕获组的匹配项。这些属性通过 RegExp. $1RegExp.$9 来访问,分别包含第 19 个捕获组的匹配项。在调用 exec()或 test()时,这些属性就会被填充,然后就可以像下面这样使用它们:

1
2
3
4
5
6
let text = "this has been a short summer"; 
let pattern = /(..)or(.)/g;
if (pattern.test(text)) {
console.log(RegExp.$1); // sh
console.log(RegExp.$2); // t
}

在这个例子中,模式包含两个捕获组。调用 test()搜索字符串之后,因为找到了匹配项所以返回true,而且可以打印出通过 RegExp 构造函数的$1 和$2 属性取得的两个捕获组匹配的内容。
2、为了方便操作原始值,ECMAScript 提供了 3 种特殊的引用类型:Boolean、Number 和 String。每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象,从而暴露出操作原始值的各种方法。来看下面的例子:
let s1 = “some text”;
let s2 = s1.substring(2);
在这里,s1 是一个包含字符串的变量,它是一个原始值。第二行紧接着在 s1 上调用了 substring()方法,并把结果保存在 s2 中。我们知道,原始值本身不是对象,因此逻辑上不应该有方法。而实际上这个例子又确实按照预期运行了。这是因为后台进行了很多处理,从而实现了上述操作。具体来说,当第二行访问 s1 时,是以读模式访问的,也就是要从内存中读取变量保存的值。在以读模式访问字符串值的任何时候,后台都会执行以下 3 步:
(1) 创建一个 String 类型的实例;
(2) 调用实例上的特定方法;
(3) 销毁实例。
可以把这 3 步想象成执行了如下 3 行 ECMAScript 代码:
let s1 = new String(“some text”);
let s2 = s1.substring(2);
s1 = null;
这种行为可以让原始值拥有对象的行为。对布尔值和数值而言,以上 3 步也会在后台发生,只不过
使用的是 Boolean 和 Number 包装类型而已。
引用类型与原始值包装类型的主要区别在于对象的生命周期。在通过 new 实例化引用类型后,得到的实例会在离开作用域时被销毁,而自动创建的原始值包装对象则只存在于访问它的那行代码执行期间。这意味着不能在运行时给原始值添加属性和方法。比如下面的例子:
let s1 = “some text”;
s1.color = “red”;
console.log(s1.color); // undefined
这里的第二行代码尝试给字符串 s1 添加了一个 color 属性。可是,第三行代码访问 color 属性时,它却不见了。原因就是第二行代码运行时会临时创建一个 String 对象,而当第三行代码执行时,这个对象已经被销毁了。实际上,第三行代码在这里创建了自己的 String 对象,但这个对象没有 color 属性。
可以显式地使用 Boolean、Number 和 String 构造函数创建原始值包装对象。不过应该在确实必要时再这么做,否则容易让开发者疑惑,分不清它们到底是原始值还是引用值。在原始值包装类型的实例上调用 typeof 会返回”object”,所有原始值包装对象都会转换为布尔值 true。
另外,Object 构造函数作为一个工厂方法,能够根据传入值的类型返回相应原始值包装类型的实
例。比如:
let obj = new Object(“some text”);
console.log(obj instanceof String); // true
如果传给 Object 的是字符串,则会创建一个 String 的实例。如果是数值,则会创建 Number 的实例。布尔值则会得到 Boolean 的实例。
注意,使用 new 调用原始值包装类型的构造函数,与调用同名的转型函数并不一样。例如:
let value = “25”;
let number = Number(value); // 转型函数
console.log(typeof number); // “number”
let obj = new Number(value); // 构造函数
console.log(typeof obj); // “object”

此页目录
2024-12-20 日报 Day41