✊不积跬步,无以至千里;不积小流,无以成江海。
Symbol的使用
Symbol 是 ECMAScript 6 中引入的一种新的原始数据类型,用于表示独一无二的标识符。它的主要特点是创建的每个 Symbol 值都是唯一的,不会与其他 Symbol 值相等。
Symbol 的使用可以有以下几个方面:
- 创建 Symbol 值:
ini
let sym1 = Symbol();
let sym2 = Symbol("description");
使用 Symbol()
构造函数创建一个新的 Symbol 值,可选参数 "description" 是可选的描述符,用于标识 Symbol 的用途或含义。
- 唯一性:
ini
let sym1 = Symbol("key");
let sym2 = Symbol("key");
console.log(sym1 === sym2); // 输出: false
每个 Symbol 值都是唯一的,即使它们的描述符相同,它们也不相等。
- Symbol 作为对象属性的键:
ini
const MY_KEY = Symbol();
let obj = {};
obj[MY_KEY] = "value";
console.log(obj[MY_KEY]); // 输出: "value"
Symbol 值可以作为对象属性的键,用于确保属性的唯一性。
- Symbol 值的隐藏属性:
javascript
const PASSWORD = Symbol();
class User {
constructor(name, password) {
this.name = name;
this[PASSWORD] = password;
}
getPassword() {
return this[PASSWORD];
}
}
let user = new User("John", "secret");
console.log(user.name); // 输出: "John"
console.log(user.getPassword()); // 输出: "secret"
console.log(user[PASSWORD]); // 输出: undefined
Symbol 值可以用于定义对象的隐藏属性,这些属性不会被常规方式访问到,但可以通过 Symbol 作为键来访问。
Symbol 的使用可以提供更好的标识符保证,避免属性冲突和重写问题,以及控制对象的隐藏属性。
Set的用法、Set实现数组去重
Set 是 ECMAScript 6 中引入的一种新的数据结构,它允许存储任何类型的唯一值,没有重复的元素。Set 内部的元素是按插入顺序排列的。
Set 的使用有以下几个方面:
- 创建 Set:
vbnet
let set = new Set();
使用 new Set()
创建一个新的 Set 对象。
- 添加元素到 Set:
csharp
let set = new Set();
set.add(1);
set.add("apple");
set.add(true);
使用 add
方法向 Set 中添加元素,保证元素的唯一性。
- 移除元素:
vbnet
let set = new Set([1, 2, 3]);
set.delete(2);
使用 delete
方法从 Set 中移除指定的元素。
- 检查元素是否存在:
vbscript
let set = new Set([1, 2, 3]);
console.log(set.has(2)); // 输出: true
console.log(set.has(4)); // 输出: false
使用 has
方法检查 Set 中是否存在指定的元素。
- 获取 Set 的大小:
arduino
let set = new Set([1, 2, 3]);
console.log(set.size); // 输出: 3
使用 size
属性获取 Set 中元素的数量。
- 遍历 Set:
javascript
let set = new Set([1, 2, 3]);
set.forEach((value) => {
console.log(value);
});
使用 forEach
方法遍历 Set 中的每个元素。
Set 可以用于实现数组去重,由于 Set 只存储唯一的值,可以很方便地过滤掉数组中的重复元素。例如:
ini
let array = [1, 2, 3, 2, 4, 1, 5];
let uniqueArray = [...new Set(array)];
console.log(uniqueArray); // 输出: [1, 2, 3, 4, 5]
上述代码中,通过将数组转换为 Set,然后使用扩展运算符 ...
将 Set 转换回数组,即可得到去重后的数组。Set 的使用可以提供高效的去重功能,并且具有简单易用的接口。
Map的用法
Map 是 ECMAScript 6 中引入的一种新的数据结构,它是一种键值对的集合,其中每个键都是唯一的。与普通对象相比,Map 提供了更灵活的键类型,并且可以保持插入顺序。
Map 的使用有以下几个方面:
- 创建 Map:
ini
let map = new Map();
使用 new Map()
创建一个新的 Map 对象。
- 添加键值对到 Map:
c
let map = new Map();
map.set("key1", "value1");
map.set("key2", "value2");
使用 set
方法向 Map 中添加键值对。
- 获取值:
arduino
let map = new Map();
map.set("key1", "value1");
console.log(map.get("key1")); // 输出: "value1"
console.log(map.get("key2")); // 输出: undefined
使用 get
方法根据键获取对应的值。
- 检查键是否存在:
arduino
let map = new Map();
map.set("key1", "value1");
console.log(map.has("key1")); // 输出: true
console.log(map.has("key2")); // 输出: false
使用 has
方法检查 Map 中是否存在指定的键。
- 移除键值对:
arduino
let map = new Map();
map.set("key1", "value1");
map.delete("key1");
console.log(map.has("key1")); // 输出: false
使用 delete
方法从 Map 中移除指定的键值对。
- 获取 Map 的大小:
arduino
let map = new Map();
map.set("key1", "value1");
console.log(map.size); // 输出: 1
使用 size
属性获取 Map 中键值对的数量。
- 遍历 Map:
c
let map = new Map();
map.set("key1", "value1");
map.set("key2", "value2");
map.forEach((value, key) => {
console.log(key, value);
});
使用 forEach
方法遍历 Map 中的每个键值对。
Map 可以用于存储键值对,并且键可以是任意类型。它提供了一种更灵活的键值对集合,适用于需要快速查找和维护插入顺序的场景。
WeakMap介绍
WeakMap 是 ECMAScript 6 中引入的一种特殊的 Map 实现,它的键必须是对象,并且对键的引用是弱引用。这意味着在没有其他引用存在时,键所对应的键值对将被自动回收,不会造成内存泄漏。
WeakMap 的特点和使用方式如下:
- 弱引用键:
WeakMap 的键必须是对象,且只有对象键的引用是弱引用。这意味着如果键对象没有被其他引用所持有,那么它们将会被垃圾回收,对应的键值对也会被自动移除。 - 键值对的添加和获取:
WeakMap 提供了set(key, value)
方法用于添加键值对,以及get(key)
方法用于根据键获取对应的值。
ini
let wm = new WeakMap();
let key = {};
let value = "Some value";
wm.set(key, value);
console.log(wm.get(key)); // 输出: "Some value"
- 检查键是否存在:
WeakMap 提供了has(key)
方法用于检查键是否存在于 WeakMap 中。
ini
let wm = new WeakMap();
let key = {};
let value = "Some value";
wm.set(key, value);
console.log(wm.has(key)); // 输出: true
- 移除键值对:
WeakMap 提供了delete(key)
方法用于移除指定的键值对。
ini
let wm = new WeakMap();
let key = {};
let value = "Some value";
wm.set(key, value);
wm.delete(key);
console.log(wm.has(key)); // 输出: false
- 弱引用的好处:
由于键是弱引用的,当键对象没有其他引用时,它们将被自动回收。这样可以避免内存泄漏问题,特别适用于需要与对象关联的附加数据,而不会干扰对象的垃圾回收。 - WeakMap 的限制:
WeakMap 没有提供像 Map 那样的迭代方法和遍历功能,也无法直接获取 WeakMap 的大小。这是因为在垃圾回收过程中,WeakMap 中的键可能被自动移除,因此无法确定准确的大小。
WeakMap 的使用场景主要是在需要与对象关联的附加数据,并且希望在对象被回收时自动移除与之关联的数据的情况下。它在某些特定的应用场景下非常有用,尤其是在处理敏感数据时。
正则表达式作用、创建、用法
正则表达式是一种用于匹配和操作文本的强大工具,它可以用于字符串的搜索、替换、验证等操作。正则表达式由一系列字符和特殊字符组成,表示一种模式,用于描述所需匹配的文本规则。
创建正则表达式有两种方式:
- 字面量方式:
ini
let regex = /pattern/;
使用正斜杠(/
)将模式包围起来,创建一个正则表达式对象。
- 构造函数方式:
ini
let regex = new RegExp("pattern");
使用 RegExp
构造函数创建一个正则表达式对象。
正则表达式的常见用法:
- 匹配:
ini
let regex = /apple/;
let str = "I have an apple.";
console.log(regex.test(str)); // 输出: true
//`regex.test(str)` 语法用于测试字符串 `str` 是否与正则表达式 `regex` 匹配。
使用 test
方法检测字符串是否匹配正则表达式。
- 搜索和提取:
ini
let regex = /apple/;
let str = "I have an apple and a banana.";
console.log(str.match(regex)); // 输出: ["apple"]
使用 match
方法在字符串中搜索并提取匹配正则表达式的部分。
- 替换:
ini
let regex = /apple/;
let str = "I have an apple.";
let newStr = str.replace(regex, "orange");
console.log(newStr); // 输出: "I have an orange."
使用 replace
方法将匹配正则表达式的部分替换为指定的字符串。
- 分割:
ini
let regex = /\s+/;
let str = "Hello World!";
console.log(str.split(regex)); // 输出: ["Hello", "World!"]
使用 split
方法根据匹配正则表达式的部分将字符串拆分为数组。
-
标志(Flags):
正则表达式可以附加标志来修改匹配的行为,常见的标志包括:
i
:忽略大小写。g
:全局匹配,匹配到所有符合条件的部分。m
:多行匹配。
ini
let regex = /apple/gi;
let str = "I have an Apple and an apple.";
console.log(str.match(regex)); // 输出: ["Apple", "apple"]
正则表达式提供了强大的文本处理能力,可以根据具体需求构建不同的模式来匹配和操作字符串。
判断输入的是否是有效手机号
要判断输入的手机号是否有效,可以使用正则表达式进行匹配。手机号的有效性规则可以根据具体需求而有所不同,以下是一个常见的手机号有效性的正则表达式示例:
javascript
function isValidPhoneNumber(phoneNumber) {
// 使用正则表达式进行匹配
let regex = /^1[0-9]{10}$/;
return regex.test(phoneNumber);
}
上述代码中,正则表达式 /^1[0-9]{10}$/
用于匹配以数字 1 开头,后面跟着 10 个数字的字符串。^
:表示字符串必须以 1
开头。 [0-9]
:表示字符串可以包含 0 到 9 的数字。{10}
:表示字符串必须包含 10 个数字。
使用示例:
ini
let phoneNumber1 = "1234567890";
console.log(isValidPhoneNumber(phoneNumber1)); // 输出: false
let phoneNumber2 = "18012345678";
console.log(isValidPhoneNumber(phoneNumber2)); // 输出: true
在上述示例中,isValidPhoneNumber
函数接受一个字符串参数 phoneNumber
,并使用正则表达式进行匹配。如果匹配成功,返回 true
,表示手机号有效;否则返回 false
,表示手机号无效。
贪婪模式和非贪婪模式
在正则表达式中,贪婪模式(Greedy mode)和非贪婪模式(Non-greedy mode)是用于控制匹配行为的两种模式。
-
贪婪模式:
默认情况下,正则表达式采用贪婪模式,即尽可能匹配更多的字符。它会尽量匹配符合模式的最长字符串。
例如,考虑以下正则表达式和字符串:
ini
let regex = /a.*/;
let str = "abcdefg";
console.log(str.match(regex)); // 输出: ["abcdefg"]
在贪婪模式下,a.*
表达式匹配以字母 "a" 开头,后面跟着任意数量的字符(包括 0 个字符)。因此,它会匹配到整个字符串 "abcdefg"
。
- 非贪婪模式:
非贪婪模式也称为懒惰模式(Lazy mode)或最小匹配模式(Minimal match mode),它与贪婪模式相反,尽量匹配更少的字符。
在正则表达式中,可以在量词(如 *
、+
、?
、{n}
等)后面加上 ?
来表示非贪婪模式。
例如,将上述例子中的正则表达式改为 /a.*?/
:
ini
let regex = /a.*?/;
let str = "abcdefg";
console.log(str.match(regex)); // 输出: ["a"]
在非贪婪模式下,a.*?
表达式匹配以字母 "a" 开头,后面跟着任意数量的字符,但尽量匹配最少的字符。因此,它只匹配到第一个字符 "a"。
正则分组实例
正则表达式中的分组(Grouping)允许将模式的一部分进行分组,并对该分组进行操作或引用。以下是一些正则分组的实例:
- 匹配重复的单词:
正则表达式可以使用分组来匹配重复的单词。例如,要匹配重复的单词 "hello",可以使用分组和反向引用\1
来实现。
ini
let regex = /(\b\w+\b)\s+\1/;
let str = "hello hello world";
console.log(regex.test(str)); // 输出: true
在上述示例中,(\b\w+\b)
表达式表示一个单词的分组,\b
是单词边界,\w+
匹配一个或多个单词字符。\s+
匹配一个或多个空白字符。\1
是反向引用,表示对第一个分组的引用,即重复的单词。
- 提取日期中的年、月、日:
分组可以用于提取日期字符串中的年、月、日等部分。
ini
let regex = /(\d{4})-(\d{2})-(\d{2})/;
let str = "2023-10-29";
let match = regex.exec(str);
console.log(match[1]); // 输出: "2023"
console.log(match[2]); // 输出: "10"
console.log(match[3]); // 输出: "29"
在上述示例中,(\d{4})
表达式表示匹配四个数字的年份,(\d{2})
表达式表示匹配两个数字的月份和日期。使用 exec
方法执行正则表达式,可以从匹配结果中提取分组的值。
- 替换匹配的部分:
分组可以用于替换匹配的部分。例如,将字符串中的 "last name, first name" 格式转换为 "first name last name" 格式:
ini
let regex = /(\w+), (\w+)/;
let str = "Doe, John";
let newStr = str.replace(regex, "$2 $1");
console.log(newStr); // 输出: "John Doe"
在上述示例中,(\w+)
分组分别匹配了姓和名。$2
和 $1
是替换字符串中的引用,表示分组的引用顺序。