- 特性:
-
- // 1、暂时行死区
- // 比如有这一个例子
- let aa = "111"
- function test(){
- console.log(aa)
- let aa = "22"
- }
- // 会报错引用错误,就是因为在函数test作用域内存在暂时性死区,如果把aa注释掉,则console.log(aa) 会打印 22
-
- // 2、没有变量提升
- // 3、不能刚重复定义
- // 4、可以产生作用域
数组解构
- const [x,y,[c]] = [1, 2,[4,5,6]];
- console.log(x,y,c); // 1 2 4
对象解构
- const {name, age, address: {city, country}} = {
- name: 'John',
- age: 30,
- address: {
- city: 'New York',
- country: 'USA'
- }
- }
- console.log(name, age, city, country); // John 30 USA
字符串解构
- // 字符串解构
- const [a, b, c, d, e] = 'hello';
- const {length : len} = 'hello';
- console.log(a, b, c, d, e, len); // h e l l o 5
- // 字符串是否包含
- const str = "hello"
- console.log(str.includes('h')); // true
- // 字符串是否以指定字符串开头
- console.log(str.startsWith('h')); // true
- // 字符串是否以指定字符串结尾
- console.log(str.endsWith('o')); // true
-
- // 以上三个方法都包含第二个参数,具体用法如下, 前两个都是从那个下标开始找,后一面一个是前n个字符串是否以 xx 结尾
- console.log(str.includes('e', 1)); // true
- console.log(str.startsWith('e', 1)); // true
- // 这个的第二个参数稍微不一样,这是相当与str.slice(0, 4).endsWidth()
- console.log(str.endsWith('l', 4)); // true
- // matchAll 使用 与 match 对比
- // matchAll 返回一个迭代器,而 match 返回匹配到的数组
-
- // 加入有這麽一個字符串 ul>li的,我们想要取出其中的值,做其他处理
- const str = `
-
-
- Item 1
-
- Item 2
-
- Item 3
-
- `
- const regex = /
- (?
.*)<\/li>/g ; -
- // 使用 match 方法
- const matchResults = str.match(regex);
- console.log(matchResults.map((v) => v.replace(/<\/?li>/g, ""))); // ["
- Item 1
", "- Item 2
", "- Item 3
"] -
- // 使用 matchAll 方法, 返回的是一个迭代器,可以通过forof 遍历, 也可以通过 [...matchAllResults].map 获取出值
- const matchAllResults = str.matchAll(regex);
- for (const match of matchAllResults) {
- console.log(match.groups.content); // "Item 1", "Item 2", "Item 3"
- }
- // 字符串重复
- const str2 = "hello"
- console.log(str2.repeat(3)); // hellohellohello
- console.log(str2.repeat(0)); // ""
- console.log(str2.repeat("2")); // "hellohello"
-
- /*
- 字符填充 padStart、padEnd,前后填充
- 第一个参数:填充完之后字符串的长度
- 第二个参数:用于填充的字符串
- */
- const str = "Hello";
- console.log(str.padStart(10, "World")); // "WorldHello"
- const num = 123;
- console.log(num.toString().padStart(10, "0")); // "0000123"
- console.log(str.padEnd(11, "World")); // "HelloWorldW"
- console.log(num.toString().padEnd(10, "0")); // "1230000"
- // 进制数表示
- const num2 = 10
- const num3 = 0b1010 // 二进制
- const num4 = 0o12 // 八进制
- const num5 = 0xA // 十六进制
- // 判断是否为NaN, Number.isNaN 不会对数字进行类型转换、对非数值都返回false
- console.log(Number.isNaN(10)); // false
- console.log(Number.isNaN("55")); // false
- console.log(Number.isNaN(NaN)); // true
- // 全局方法 isNaN 会对要判断的值进行类型转换,转换成数字,再判断
- console.log(isNaN(10)); // false
- console.log(isNaN("55")); // false
- console.log(isNaN(NaN)); // true
- console.log(isNaN("abc")); // true
-
- // 判断是否为有限数 对于非数值都返回false
- console.log(Number.isFinite(10)); // true
- console.log(Number.isFinite("55")); // false
- console.log(Number.isFinite(NaN)); // false
- console.log(Number.isFinite(Infinity)); // false
- console.log(Number.isFinite(100/0)); // false
-
- // 全局方法 isFinite 会对要判断的值进行类型转换,转换成数字,再判断, 对于转不成数值的字符串,会返回false
- console.log(isFinite(10)); // true
- console.log(isFinite("55")); // true
- console.log(isFinite(NaN)); // false
- console.log(isFinite(Infinity)); // false
- console.log(isFinite(100/0)); // false
- console.log(isFinite("abc")); // false
- /*
- bigInt
- 由于number 的数值范围是-2^53 2^53,所以无法精确表示大于 2^53 的数值,所以就需要bigint这个数值类型
- */
-
- // bigint 不能与 number 进行运算
- // 因为 bigint 无法与 number 进行隐式转换
-
- let bigIntValue = 123n;
- let numberValue = 123;
- // console.log(bigIntValue + numberValue); // 报错
- console.log(bigIntValue + BigInt(numberValue)); // 246n
-
- // 但是可以进行比较
- console.log(bigIntValue == numberValue); // true
- console.log(bigIntValue === numberValue); // false
- // 扩展运算符
- const arr1 = [1, 2, 3];
- const arr2 = [4, 5, 6];
- const arr3 = [...arr1, ...arr2]; // 浅层复制
- console.log(arr3); // [1, 2, 3, 4, 5, 6]
-
- // 剩余参数
- const [a, b, ...rest] = [1, 2, 3, 4, 5];
- console.log(a); // 1
- console.log(b); // 2
- console.log(rest); // [3, 4, 5]
-
-
-
- // Array.from 可以将类数组转成数组
- function foo() {
- return Array.from(arguments);
- }
- console.log(foo(1, 2, 3)); // [1, 2, 3]
- // 还可以像 map 的回调函数那样使用
- const arr = Array.from([1, 2, 3], x => x \* 2);
- console.log(arr); // [2, 4, 6]
-
- // Array.of 用于创建一个具有可变数量参数的新数组实例,而不考虑参数化的数量
- console.log(Array.of(1, 2, 3)); // [1, 2, 3]
- console.log(Array.of(3)); // [3]
- // 与 Array 构造函数不同,Array 当只有一个参数的情况下,返回的是一个长度为 n 的空数组
- console.log(Array(3)); // [ , , ]
- // fill
- const arr6 = [1, 2, 3, 4, 5];
- arr6.fill(0, 1, 3); // 将索引 1 到索引 3 的元素替换为 0
- console.log(arr6); // [1, 0, 0, 4, 5]
- // fill 方法还可以用于数组的初始化
- const arr7 = new Array(5).fill(0); // 创建一个长度为 5 的空数组
- console.log(arr7); // [0, 0, 0, 0, 0]
-
- // find 与 findIndex 查找满足指定条件的第一个元素,分别返回该元素和索引
- const arr4 = [1, 2, 3, 4, 5];
- const found = arr4.find(x => x > 3); // 返回值
- console.log(found); // 4
- const foundIndex = arr4.findIndex(x => x > 3); // 返索引
- console.log(foundIndex); // 3
-
- // findLast 与 findLastIndex 查找满足指定条件的最后一个元素,分别返回该元素和索引,需要注意的是 node 版本需要比较新的版本,才支持这两个方法,比如 18.17.1
- const arr5 = [1, 2, 3, 4, 5];
- const foundLast = arr5.findLast(x => x > 3); // 返回值
- console.log(foundLast); // 5
- const foundLastIndex = arr5.findLastIndex(x => x > 3); // 返索引
- console.log(foundLastIndex); // 4
- // flat flatMap
- const arr8 = [1, 2, [3, 4, [5, 6]]];
- const flatArr = arr8.flat(); // 默认只会将数组拉平一层
- console.log(flatArr); // [1, 2, 3, 4, [5, 6]]
- const flatArr2 = arr8.flat(2); // 拉平多层
- console.log(flatArr2); // [1, 2, 3, 4, 5, 6]
- // key-map 的数组对象数组, 可以使用 flatMap 来扁平化
- const arr9 = [{name: 'xx', list: [1,2,3]}, {name: 'yy', list: [4,5,6]}];
- const flatMapArr = arr9.flatMap(x => x.list); // 会将每个 list 扁平化,相当于先调用map,再 flat
- console.log(flatMapArr); // [1, 2, 3, 4, 5, 6]
- // 扩展运算符
- const person1 = {
- name: 'John',
- age: 30
- };
- const person2 = {
- ...person1,
- name: 'Jane'
- };
- console.log(person2); // 输出: { name: 'Jane', age: 30 }
- // Object.assign()
- const person3 = {
- name: 'John'
- };
- const person4 = {
- age: 30
- };
- const person5 = {
- course: 99
- };
- Object.assign(person3, person4, person5);
- console.log(person3); // 输出: { name: 'John', age: 30, course: 99}
- // Object.is
- const person6 = {
- name: 'John',
- age: 30
- };
- const person7 = {
- name: 'John',
- age: 30
- }
- console.log(Object.is(person6, person7)); // 输出: false
- console.log(Object.is(NaN, NaN)); // 输出: true
- console.log(Object.is(+0, -0)); // 输出: false
- // 与 === 运算符的区别
- console.log(+0 === -0); // 输出: true
- console.log(NaN === NaN); // 输出: false
- // Object.fromEntries() 方法把键值对列表转换为一个对象。
- // 例如,将一个 Map 结构转换为对象:
- const entries = new Map([
- ['foo', 'bar'],
- ])
- console.log(Object.fromEntries(entries)); // { foo: 'bar' }
-
-
- // 用法2
- const obj = {
- name: 'John',
- age: 30,
- city: 'New York'
- }
-
- const keyValues = Object.entries(obj);
- console.log(keyValues); // [ [ 'name', 'John' ], [ 'age', 30 ], [ 'city', 'New York' ] ]
- console.log(Object.fromEntries(keyValues)); // { name: 'John', age: 30, city: 'New York' }
-
- // 用法3
- // 将一个 URLSearchParams 结构转换为对象:
- const paramsString = 'q=URLUtils.searchParams&topic=api';
- const searchParams = new URLSearchParams(paramsString);
- // 当然也可以像这样获取 searchParams.get
- console.log(searchParams.get('q')); // URLUtils.searchParams
- console.log(searchParams.get('topic')); // api
- console.log(Object.fromEntries(searchParams)); // { q: 'URLUtils.searchParams', topic: 'api' }
-
-
-
- // 函数参数默认值,注意假如有多个参数,默认值只能从最后开始放
- function greet(name = 'World') {
- console.log(`Hello, ${name}!`);
- }
- greet(); // 输出:Hello, World!
- greet('Alice'); // 输出:Hello, Alice!
-
- // 剩余参数,主要是平替 arguments
- function sum(...nums) {
- return nums.reduce((a, b) => a + b, 0);
- }
- console.log(sum(1, 2, 3, 4, 5)); // 输出:15
- function printNums(x, y, ...nums) {
- console.log(x, y, nums);
- }
- printNums(1, 2, 3, 4, 5); // 输出:1 2 [3, 4, 5]
- /*
- 箭头函数, 当只有一个参数时,可以省略小括号,当函数体只有一个表达式时,可以省略大括号和 return 关键字
- 如果返回值是对象,需要用小括号包起来
- 没有this(与上下文同一个),无法访问arguments, 无法作为构造函数
- */
- const add = (a, b) => a + b;
- console.log(add(1, 2)); // 输出:3
- // 创建Symbol
- const sym1 = Symbol();
- const sym2 = Symbol('key'); // 带有描述的字符串
- // console.log(sym1 > "666"); // Cannot convert a Symbol value to a number
- // 显示调用 toString
- console.log(sym2.toString() + "666"); // Symbol(key)666
- // 隐式转换boolean
- if (sym2) {
- console.log("symbol is true"); // symbol is true
- }
-
-
- // symbol 作为对象属性名,就不会出现属性覆盖的情况了
- const sym3 = Symbol();
- const obj = {};
- obj[sym3] = "symbol property";
- console.log(obj[sym3]); // symbol property
- const obj1 = {...obj}
- console.log(obj1[sym3]); // symbol property
- // 一些防止意外更改的属性,,可以传一个字符串作为symbol描述,方便查看对象的时候区别那个属性
- const keys = {
- name: Symbol("name"),
- age: Symbol("age"),
- gender: Symbol("gender"),
- hobby: Symbol("hobby")
- }
-
- const obj2 = {
- [keys.name]: "张三",
- [keys.age]: 18,
- [keys.gender]: "男",
- [keys.hobby]: "篮球",
- other: "其他"
- }
- console.log(obj2[keys.name]); // 张三
-
- // 不能forin遍历,这块的结果是啥也不打印
- for (const key in obj2) {
- console.log(key);
- }
-
- // 能用Object.getOwnPropertySymbols获取
- console.log(Object.getOwnPropertySymbols(obj2)); // [Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby)]
- // 也可以用Reflect.ownKeys
- console.log(Reflect.ownKeys(obj2)); // [ 'other', Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby) ]
-
- /*
- symbol 作为常量, 为啥要这么是用,就是为了避免本来定义的常量的情况下
- 例如 const COLOR_RED = "red"; 然後在用的时候非 getComplement("red")这么用,而不是getComplement(COLOR_RED)这么用
- 使用symbol 作为常量,可以防止上面的问题
- */
- const COLOR_RED = Symbol();
- const COLOR_GREEN = Symbol();
-
- function getComplement(color) {
- switch (color) {
- case COLOR_RED:
- return "RED";
- case COLOR_GREEN:
- return "GREEN";
- default:
- }
- }
-
- // 测试
- console.log(getComplement(COLOR_RED)); // COLOR_GREEN
- console.log(getComplement(COLOR_GREEN)); // COLOR_RED
-
- // Symbol 获取描述符的方法
- const sym = Symbol('name');
- console.log(sym.description); // 输出 "name"
Symbol.iterator的作用
* 1、是为各种数据结构,提供一个统一的、简便的访问接口
* 2、是使得数据结构的成员能够按某种次序排列
* 3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
* 4、一个数据结构只要部署了Iterator接口,我们就称这种数据结构是“可遍历的”
* 5、原生具有迭代器的数据结构 Array Map Set String NodeList arguments 后面两个是伪数组
- // 获取迭代器
- const arr = ["a", "b", "c"];
- const iter = arr[Symbol.iterator]();
- // 使用next方法遍历
- console.log(iter.next()); // { value: 'a', done: false }
- console.log(iter.next()); // { value: 'b', done: false }
- console.log(iter.next()); // { value: 'c', done: false }
- console.log(iter.next()); // { value: undefined, done: true }
-
- // 线性对象 增加迭代器, 则对象就可以使用for...of循环遍历了
- const obj = {
- 0: "a",
- 1: "b",
- 2: "c",
- length: 3,
- [Symbol.iterator]: Array.prototype[Symbol.iterator]
- }
- for (const c of obj) {
- console.log(c);
- }
- // 自定义迭代器
- const obj2 = {
- data: ["a", "b", "c"],
- [Symbol.iterator]() {
- let index = 0;
- return {
- next: () => ({
- value: this.data[index++],
- done: index > this.data.length
- })
- }
- }
- }
- const iter2 = obj2[Symbol.iterator]();
- console.log(iter2.next()); // { value: 'a', done: false }
- console.log(iter2.next()); // { value: 'b', done: false }
- console.log(iter2.next()); // { value: 'c', done: false }
- console.log(iter2.next()); // { value: undefined, done: true }
-
- // 配合扩展运算符,或者Array.from,容有迭代器的数据结构,都会自动转成数组
- const arr2 = [...obj2];
- console.log(arr2); // ['a', 'b', 'c']
- console.log(Array.from(obj2)); // ['a', 'b', 'c']
- // set 介绍及其使用
- // 创建一个Set对象
- const mySet = new Set();
-
- // 添加元素
- mySet.add(1);
- mySet.add(2);
- mySet.add(3);
-
- // 检查元素是否存在
- console.log(mySet.has(2)); // 输出 true
- console.log(mySet.has(4)); // 输出 false
-
- // 删除元素
- mySet.delete(2);
-
- // 获取Set的大小
- console.log(mySet.size); // 输出 2
-
- // 遍历Set
- for (let value of mySet) {
- console.log(value); // 输出 1, 3
- }
- // 将Set转换为数组
- console.log(Array.from(mySet)); // 输出 [1, 3]
- console.log([...mySet]); // 输出 [1, 3]
-
- // 清空Set
- mySet.clear();
-
- // 检查Set是否为空
- console.log(mySet.size === 0); // 输出 true
-
- // 合并Set
- const set1 = new Set([1, 2, 3]);
- const set2 = new Set([2, 3, 4]);
- const unionSet = new Set([...set1, ...set2]);
- console.log(unionSet); // 输出 Set { 1, 2, 3, 4 }
-
- // keys values entries set的键、值都是相同的
- const mySet1 = new Set(['a', 'b', 'c']);
-
- for (let key of mySet1.keys()) {
- console.log(key); // 输出 'a', 'b', 'c'
- }
-
- for (let value of mySet1.values()) {
- console.log(value); // 输出 'a', 'b', 'c'
- }
-
- for (let entry of mySet1.entries()) {
- console.log(entry); // 输出 ['a', 'a'], ['b', 'b'], ['c', 'c']
- }
-
- // 结合set实现一个去重复杂数组
- function uniqueArray(arr) {
- const uniSet = new Set();
- return arr.filter((item)=>{
- const str = JSON.stringify(item);
- if (uniSet.has(str)) {
- return false;
- }else{
- uniSet.add(str);
- return true;
- }
- })
- }
-
- const arr = [1, 1, 3, 4, {name:12}, {name:12}, [1,2], [1,2]];
- console.log( uniqueArray(arr)); // [ 1, 3, 4, { name: 12 }, [ 1, 2 ] ]
- // 创建一个 Map 对象
-
- constkeyObj= {name:11}
-
- constmyMap=newMap([
-
- ["aa", 11],
-
- ["bb", 22],
-
- [keyObj, 33],
-
- [55, 33],
-
- ]);
-
- // 添加键值对
-
- myMap.set("cc", 44);
-
- console.log(myMap); // Map(5) { 'aa' => 11, 'bb' => 22, { name: 11 } => 33, 55 => 33, 'cc' => 44 }
-
- // 是否包含某个键
-
- console.log(myMap.has("aa")); // true
-
- // 删除键值对
-
- myMap.delete(keyObj);
-
- console.log(myMap); // Map(4) { 'aa' => 11, 'bb' => 22, 55 => 33, 'cc' => 44 }
-
- // 获取键值对数量
-
- console.log(myMap.size); // 4
-
- // 遍历 Map
-
- for (constitemofmyMap) {
-
- console.log(item); // 输出键值对 [ 'aa', 11 ] [ 'bb', 22 ] [ 55, 33 ] [ 'cc', 44 ]
-
- }
-
- // 转成数组
-
- console.log([...myMap]); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
-
- console.log(Array.from(myMap)); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
-
- // 清空 Map
-
- myMap.clear();
-
- console.log(myMap); // Map(0) {}
- /*
- Proxy 它的作用实在对象与对象的属性之间架设一个代理,用于对对象的操作进行拦截和改写,
- 它提供了一种机制,可以拦截并修改对象的任意属性,或者对属性进行操作。
- */
-
- const target = {
- name: 'John',
- age: 30
- };
-
- const proxy = new Proxy(target, {
- get: function(target, property, receiver) {
- console.log(`Getting ${property}`);
- return target[property];
- },
- set: function(target, property, value, receiver) {
- console.log(`Setting ${property} to ${value}`);
- target[property] = value;
- }
- })
- console.log(proxy.name); // 输出 "Getting name" 和 "John"
- proxy.age = 40; // 输出 "Setting age to 40"
- console.log(target.age); // 输出 40,target会与proxy同时改变
Reflect 可以用于获取目标对象的行为,他与Object类似,但是更加易读,为了操作
对象提供了一种更加优雅的方式,它的方法与Proxy时对应的,代替Object 的部分方法
- const obj = {
- name: 'why',
- age: 18
- }
-
- /**
- * 获取与设置对象属性
- */
- // 获取对象上的属性
- const name = Reflect.get(obj, 'name')
- console.log(name) // why
- // 设置对象的属性
- Reflect.set(obj, 'address', '北京市')
-
- /**
- * 函数代替命令式的写法
- * delete obj.name --> Reflect.deleteProperty(obj, 'name')
- * name in obj --> Reflect.has(obj, 'name')
- */
- // 判断对象上是否有指定属性
- const hasName = Reflect.has(obj, 'name')
- console.log(hasName) // true
-
- // 删除对象的属性
- Reflect.deleteProperty(obj, 'age')
- console.log(obj); // { name: 'why', address: '北京市' }
- /**
- * 一般是与 proxy一起使用的
- */
- // 代理对象
- const arr = [1,2,3]
- // 代理配置
- const proxy = new Proxy(arr, {
- get(target, key) {
- // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
- console.log("get", target, key); //get [ 1, 2, 3 ] push get [ 1, 2, 3 ] length
- return Reflect.get(target, key)
- },
- set(target, key, value) {
- console.log(target, key, value); // [ 1, 2, 3 ] push 4 [ 1, 2, 3, 4 ] length 4
- // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
- return Reflect.set(target, key, value)
- }
- })
- proxy.push(4);
-
-
-
-
- // 设置对象的属性的操作
- const obj2 = {
- name: 'kobe',
- age: 30
- }
-
- // 设置属性
- Reflect.defineProperty(obj2, 'address', {
- value: '上海市',
- writable: false, // 是否可以修改
- })
-
-
-
-
-
- /*
- 修改了Object部分方法分返回结果
- Object.defineProperty() 如果执行失败,会抛出错误 -> Reflect.defineProperty()执行失败则会返回false
- 下面搞两个例子作对比
- */
- console.log(
- Reflect.defineProperty(obj2, 'address', {
- value: '广州市',
- })
- ); // false
-
- Object.defineProperty(obj2, 'xxx', {
- value: 'xx',
- writable: false, // 是否可以修改
- })
- Object.defineProperty(obj2, 'xxx', {
- value: '66',
- }) // 报错 Cannot redefine property: xxx
-
- /**
- * class 语法糖使用
- * 可以写 get 、 set 方法, 但是实际中不建议使用,这里就不写相关 demo 了
- * 也可以写静态方法 static 开头
- */
- class Person {
- static money = 100; // 静态属性
- static getMoney() { // 静态方法
- return Person.money;
- }
- constructor(name, age) {
- this.name = name;
- this.age = age;
- }
-
- greet() {
- console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
- }
- }
-
- const person = new Person('John', 25);
- person.greet(); // 输出:Hello, my name is John and I am 25 years old.
- console.log(Person.getMoney(), Person.money); // 输出 100 100
-
- // 继承, 父类的静态方法、属性也会被继承
- class Student extends Person {
- constructor(name, age, grade) {
- // 调用父类的构造函数
- super(name, age);
- this.grade = grade;
- }
-
- // 可以重写父类的方法
- greet() {
- // 可以通过 super 访问父类的方法
- super.greet();
- console.log(`Hello, my name is ${this.name} and I am ${this.age} years old. I am in grade ${this.grade}.`);
- }
-
- // 也可以添加自己的方法
- study() {
- console.log(`${this.name} is studying.`);
- }
- }
-
- const student = new Student('Alice', 18, 'A');
- student.greet(); // 输出:Hello, my name is Alice and I am 18 years old. Hello, my name is Alice and I am 18 years old. I am in grade A.
- student.study(); // 输出:Alice is studying.
- console.log(Student.money, Student.getMoney()); // 输出 100 100
- const str = '百度';
- // 捕获了两个命名组,分别是 url 和 text
- const reg = /(?
.*)<\/a>/ ; -
- const result = reg.exec(str);
- console.log(result.groups.url); // https://www.baidu.com
- console.log(result.groups.text); // 百度
- var str = "今天是2024-06-11";
- var regex = /(?
\d{4})-(?\d{2})-(?\d{2})/ d; -
- /**
- * 输出 includes就是 各个匹配组的开始及结束下标
- * [
- '2024-06-11',
- '2024',
- '06',
- '11',
- index: 3,
- input: '今天是2024-06-11',
- groups: [Object: null prototype] { year: '2024', month: '06', day: '11' },
- indices: [
- [ 3, 13 ], // "2024-06-11" 的开始即结束下标
- [ 3, 7 ],
- [ 8, 10 ],
- [ 11, 13 ],
- groups: [Object: null prototype] {
- year: [Array],
- month: [Array],
- day: [Array]
- }
- ]
- ]
- */
- console.log(regex.exec(str));
主要是与for await结合使用
- // 同步迭代器、简单使用
- function *gen(){
- yield 1;
- yield 2;
- yield 3;
- }
-
- for(let value of gen()){
- console.log(value); // 输出:1 2 3
- }
-
- // promise 中有定時器
- function timer(time){
- return new Promise(resolve => {
- setTimeout(()=>{
- resolve(`data-${time}`)
- }, time);
- });
- }
-
-
- // 同步迭代器返回 promise
- function *gen2(){
- yield timer(1000);
- yield timer(2000);
- yield timer(3000);
- }
-
- const g = gen2();
-
- for(let value of g){
- console.log(value); // 输出:Promise {
} Promise { } Promise { } - }
-
- // 异步生成器
- async function *gen3(){
- yield timer(1000);
- yield timer(2000);
- yield timer(3000);
- }
-
- async function test(){
- const g3 = gen3();
- // 三个异步生成器生成的 任务,这里不是同步执行的,是分别执行完,再从头开始执行的
- // 与普通的promise 普通的是并行执行的,分别会在第1、2、3秒输出结果
- const arr = [g3.next(), g3.next(), g3.next()];
- for await(const req of arr){
- console.log(req.value); // 第一秒的时候: data-1000 第三秒的时候:data-2000 第六秒的时候:data-3000
- }
- }
- test()
-
-
-
-
- DOCTYPE html>
-
-
-
异步迭代 -
- // module 新增 动态导入 import()
- async function dynamicImport() {
- const modulePath = './module.js';
- // then写法
- // import(modulePath)
- // .then((module) => {
- // // 在这里可以使用动态导入的模块
- // module.default();
- // })
- // .catch((error) => {
- // console.error('模块加载失败:', error);
- // });
-
- // await 写法
- const module = await import(modulePath);
- console.log(module); // 输出: { default: [Function] }
- }
- dynamicImport()
-
-
module.js
- export default {
- name: 666
- }
-
- export function test(){}
统一管理模块
export * as obj from "xxx" // 从其他模块导入东西在当前模块,并且与当前模块的东西一并导出去,在其他的地方使用的时候就引入当前模块即可
提供一种标准方式,让我们在不同环境可以获取到对应的顶层对象、比如像浏览器环境的window、node环境的global等
- // &&=
- let a = 10
- a &&=20
- console.log(a) // 20
-
- let b = 0
- b &&=20
- console.log(b) // 0
-
- // ||=
- let c = 10
- c ||=20
- console.log(c) // 10
-
- let d = 0
- d ||=20
- console.log(d) // 20
-
- // ??=
- let e = 10
- e ??=20
- console.log(e) // 10
-
- let f = 0
- f ??=20
- console.log(f) // 0
-
- // 示例
- let user = null
- user ??=666
- console.log(user) // 666
-
-
-
- // 数值分隔符
- let num = 123_456_789;
- console.log(num, num === 123456789); // 输出: 123456789 true
-
- let num2 = 123.456;
- console.log(num2); // 输出: 123.456
-
- let num3 = 123_456.789;
- console.log(num3); // 输出: 123456.789
-
- // 其他进制也可以这样表示
- let binaryNum = 0b1010_1010;
- console.log(binaryNum); // 输出: 170
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>weakSettitle>
- head>
- <body>
- <script>
- /**
- * weakSet
- * 类似于set,但是成员都是弱引用(且不嗯呢该是基本类型,只能是复杂类型),即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,
- * 如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。
- * 只有add delete has三个方法
- */
- const ws = new WeakSet();
- let obj = {name: 111};
- let foo = {age: 18};
-
- ws.add(foo);
- ws.add(obj);
-
- console.log(ws.has(obj)); // true
- console.log(ws.has(foo)); // true
- console.log(ws); // WeakSet {Object {name: 111}, Object {age: 18}}
-
- // foo = null; // 标记没了,则会被清除,不会考虑ws 中的东西
- // console.log(ws.has(foo)); // false
- // console.log(ws); // WeakSet {Object {name: 111}}
-
-
- // 与set 对比的话
- /*
- 1. set 中的元素可以是基本类型,也可以是复杂类型,而WeakSet 中的元素只能是复杂类型
- 2. WeakSet 中的元素都是弱引用,而set 中的元素都是强引用
- 3. WeakSet 中的元素都是不可枚举的,而set 中的元素都是可枚举的
- 4. WeakSet 中的元素都是不可遍历的,而set 中的元素都是可遍历的
- */
- // 1. 基本类型
- let ws2 = new Set();
- let obj2 = {name: 111};
- let foo2 = {age: 18};
-
- ws2.add(foo2);
- ws2.add(obj2);
-
- console.log(ws2.has(obj2)); // true
- console.log(ws2.has(foo2)); // true
- console.log(ws2); // Set(2) {Object {name: 111}, Object {age: 18}}
-
- foo2 = null; // 标记没了,则会被清除,不会考虑ws 中的东西
- console.log(ws2.has(foo2)); // false
- console.log(ws2); // Set(1) {Object {name: 111}, Object {age: 18}} 引用还是在,就会出现问题
-
-
-
- script>
- body>
- html>
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>异步迭代title>
- head>
- <body>
- <script>
- /**
- * weakMap
- * 类似于map,但是key只能是对象,不能是其他类型
- * 只有get set delete has四个方法
- * 不能遍历、垃圾回收机制会自动回收
- * 应用场景:
- * 1、存储一些需要频繁访问的数据
- */
- const weakMap = new WeakMap();
- let obj = { name: 'zs' };
- weakMap.set(obj, 'value');
- console.log(weakMap.get(obj)); // value
- console.log(weakMap.has(obj)); // true
- console.log("有值", weakMap); // WeakMap { key:{ name: 'zs' }, value: 'value' }
-
- obj = null
- console.log("无值", weakMap); // WeakMap {} 如果是 Map 则这里会有值,就有可能会造成内存泄漏的情况
- script>
- body>
- html>
以上便是本次ES6 查漏补缺的记录,欢迎留言交流,共勉