# es6~es13

# 对象字面量增强写法

# 对象属性成员简写

如果成员名称的key和value相同时可以简写

const name = "张三";
const age = 18;
const obj = {
    name,
    age
}
console.log(obj);//{name: '张三', age: 18, fun: ƒ, fun1: ƒ, fun2: ƒ}

# 对象方法成员简写

注意

箭头函数写法this指向window

const name = "张三";
const age = 18;
const obj = {
    //原始写法
    //具有this指向 this指向当前对象
    fun: function () {
        console.log("原始写法", this);
    },
    //es6新写法
    fun1() {
        console.log("es6", this);
    },
    //箭头函数写法
    //无this指向
    fun2: () => {
        console.log("箭头函数", this);
    },
};
obj.fun();//原始写法 {name: '张三', age: 18, fun: ƒ, fun1: ƒ, fun2: ƒ}
obj.fun1();//es6 {name: '张三', age: 18, fun: ƒ, fun1: ƒ, fun2: ƒ}
obj.fun2();//箭头函数 {}

# 数组和对象的解构

# 数组解构

# 普通解构

const names = ["张三", "李四", "王五"];
//数组解构
const [name1, name2, name3] = names;
console.log(name1, name2, name3);//张三 李四 王五

# 从数组第二项解构,使用逗号进行占位

const [, name21, name31] = names;
console.log(name21, name31);//李四 王五

# 使用剩余参数 将数组项放入一个新数组中

const [name211, ...name311] = names;
console.log(name211, "剩余参数", name311);//张三 剩余参数 (2) ['李四', '王五']

# 解构默认值

当解构出的数组项为undefind时 会取解构默认值

const [name1111, name2221, name3331 = "123", name4441 = "王德发"] = names;
console.log(name1111, name2221, name3331, name4441); //张三 李四 王五 王德发

# 数组解构问题

数组解构时只能根据数组项索引从左往右依次解构 虽有,号进行占位,但当数组项非常多时解构数组最后一位变得非常麻烦

# at(数组索引)函数获取数组最后一位

//获取数组第一位
const name11111 = names.at(0);
console.log(name11111);//张三
//获取数组最后一位
const nameFinally = names.at(-1);
console.log(nameFinally);//王五

# 对象解构

对象解构可以根据对象成员的key值进行索引
因此对象解构可以不根据对象成员顺序进行解构

const obj = {
    name: "张三",
    age: 18,
    height: 180,
};
const {height, name, age} = obj;
console.log(name, age, height); //张三 18 180

# 对象解构变量重命名

对象解构的名称可能重复 重命名解构名称可解决

const {name: newName} = obj;
console.log(newName); //张三

# 对象解构默认值

当解构的变量可能不存在时可以使用对象解构默认值

const {address = "昆明"} = obj; //obj中无address属性
console.log(address); //昆明

# 对象解构剩余参数

与数组解构剩余参数相同,解构的剩余参数会放入一个新的对象中

const {name: name890, age: age68, ...all} = obj;
console.log(name890, age68, all);//张三 18 {height: 180}

# let/const作用域提升

作用域提升本质就是能不能在变量声明前使用
var为例 var有作用域提升
使用var声明的变量会被挂在到window上

console.log(foo)
var foo = '123'

# 模版字符串的使用

const name = "张三";
const age = 18;
//正常使用
console.log(`${name}今年${age}`);//张三今年18岁
//拼接表达式
console.log(`${name}明年${age + 1}`); //张三明年19岁
//拼接函数
const getAge = () => age + 10;
console.log(`${name}十年后${getAge()}`); //张三十年后28岁

# 标签模板字符串

标签模板字符串是一种调用函数的方式

const fun = (a, b, ...c) => {
    console.log(a, b, c);
};
const name = "张三";
const age = 18;
//标签模板字符串是一种调用函数的方式
//不传任何参数
fun``; //[ '' ] undefined []
//传递一个参数
fun`hellow word`; //[ 'hellow word' ] undefined []
//使用模板字符串
fun`hellow word${age}${name}`; //[ 'hellow word', '', '' ] 18 [ '张三' ]
fun`hel${age}low ${name}word`; //[ 'hel', 'low ', 'word' ] 18 [ '张三' ]

测试可得在使用标签模板字符串调用函数时${}会把字符串切割为多段生成一个数组,最后赋值给函数的第一个形参
${}中的数据${age}、${name}会赋值给函数的第一。第二个形参

# 函数的默认参数

# es5 定义默认参数

function fun(name, age) {
    name = name || '张三'
    age = age || 18
    console.log(name, age)
}

fun('', 0)//张三 18

从运行结果可知在使用||、&&运算符时0和‘’默认为false

# es6默认参数写法

const fun = (name = "张三", age = 18) => {
    console.log(name, age);
};
fun();//张三 18
fun("", 0);// 0

有默认值的函数的`length`属性

有默认值的函数不算在length之内,并且默认值之后的所有参数都不算在length之内

//无默认值
const fun = (name, age) => {
    console.log(name, age);
};
console.log("fun形参长度", fun.length);//2
//有默认值
const fun1 = (name, age = 18) => {
    console.log(name, age);
};
console.log("fun1形参长度", fun1.length);//1
//默认值之后有参数
const fun2 = (name, age = 18, height, sex) => {
    console.log(name, age);
};
console.log("fun1形参长度", fun2.length);//1

# 对象参数结构默认值

const fun2 = ({name, age} = {name: "张三", age: 18}) => {
    console.log("对象参数结构默认值", name, age);
};
const obj = {name: "李四", age: 80};
fun2();//张三 18
fun2(obj);//李四 80

//简写形式
const fun3 = ({name = "张三", age = 18} = {}) => {
    console.log("对象参数结构默认值简写", name, age);
};
fun3();//张三 18
fun3(obj);//李四 80

注意

有默认值的形参最好放在最后
默认值形参放在最后 函数调用时有默认值的形参可以不写

const fun = (x, y, z = 1) => console.log(x, y, z)

fun(1, 2)

# 函数的剩余参数

使用前缀运算符...声明的形参,会讲剩余的所用参数赋值进一个新的数组中

注意

前缀运算符...只能在形参的最后一位声明

const fun = (name, ...all) => {
    console.log(name, all);
};
fun("张三", 18, "男");//张三 (2) [18, '男']

# 展开运算符的使用

# 在函数调用时使用展开运算符

const names = ["张三", "李四", "王五"];
const name = "王德法";

const fun = (x, y, z) => {
    console.log(x, y, z);
};
//在函数调用时使用展开运算符
//展开数组
fun(...names); //张三 李四 王五
//展开字符串
fun(...name); //王 德 法

# 在构建数组时使用展开运算符

const nameAll = [...names, "123"];
console.log(nameAll); //['张三', '李四', '王五', '123']

# 在构建对象时使用展开运算符

const obj = {name: "张三", age: 18, sex: "男"};
const newObj = {...obj, height: 180};
newObj.height = 123
console.log(newObj);//{name: '张三', age: 18, sex: '男', height: 180}
console.log(obj)

注意

展开运算符只用的是浅拷贝

const obj = {name: "张三", age: 18, sexobg: {sex1: "男"}};
const newObj = {...obj, height: 180};
newObj.sexobg.sex1 = "女";
console.log(newObj); //{ name: '张三', age: 18, sexobg: { sex1: '女' }, height: 180 }
console.log(obj); //{ name: '张三', age: 18, sexobg: { sex1: '女' } }

# 逗号运算符的基本使用

逗号运算符是二元运算符,它能够先执行运算符左侧的操作数,然后再执行右侧的操作数,最后返回右侧操作数的值。

# 逗号运算符可以实现连续运算,如多个变量连续赋值。

const a = 1, b = 2, c = 3;
console.log(a, b, c)//1 2 3

注意

与条件运算符、逻辑运算符根据条件来决定是否执行所有或特定操作数不同的是,逗号运算符会执行所有的操作数,但并非返回所有操作数的结果,它只 返回最后一个操作数的值

在下面代码中,变量 a 的值是逗号运算之后,通过第二个操作数 c=2 的执行结果赋值得到的。第一个操作数的执行结果没有返回,但是这个表达式被执行了。

let a = (b = 1, c = 2)
console.log(a)//2
console.log(b, c)//1 2

逗号运算符可以作为仅需执行表达式的工具,这些表达式不需要返回值,但必须要运算。在特定环境中,可 以在一个表达式中包含多个子表达式,通过逗号运算符让它们全部执行,而不用返回结果。

const run = () => (console.log(456), console.log(123));
run()// 456    123

# 表示数值

const num = 100; //十进制
const num1 = 0b100; //二进制 二进制需要0b开头
const num2 = 0o100; //八进制 八进制需要0o开头
console.log(num, num1, num2); //100 4 64

//大的数据 位数连接符
const bigNum = 10_000_000_000;
console.log(bigNum); //10000000000

# Symbol数据类型

# 为什么需要Symbol

  1. 在es6之前对象的属性名都是字符串形式 很容易造成属性命名冲突
  2. 比如原来有一个对象 我们希望在其中添加新的属性和值,但是我们不确定它原来内部有什么内容的情况下 很容易造成命名冲突 从而覆盖掉它内部的某个属性
  3. 比如开发中使用了混入 那么混入中属性出现同名 必然会有一个被覆盖掉

Symbol的出现就是为了解决这些问题
Symbol的作用是生成一个独一无二的值

const s1 = Symbol();
const s2 = Symbol();
console.log(s1 === s2); //false

Symbol的值是通过Symbol()函数来实现的,生成后可以作为属性名
在es6中,对象的属性名可以使用字符串,也可以使用Symbol值

# Symbol 的描述形参 description

在es10中,Symbol可以传入一个描述,类型为数字或字符串

const s3 = Symbol("张三");
const s4 = Symbol(18);
console.log(s3, s3.description);//Symbol(张三) 张三
console.log(s4, s4.description);//Symbol(18) 18

# 使用Symbol值作为对象属性key

const s5 = Symbol();
const s6 = Symbol();
const s7 = Symbol();
//使用对象计算属性名
const obj = {
    [s5]: "张三",
    [s6]: "18",
    hobby: "篮球",
};
console.log(obj, obj[s5]); //{hobby: '篮球', Symbol(): '张三', Symbol(): '18'} 张三
//新增属性
obj[s7] = "男";
console.log(obj); //{hobby: '篮球', Symbol(): '张三', Symbol(): '18', Symbol(): '男'}

注意

  1. 使用Symbol创建的属性名不能通过.语法获取
console.log(obj.s5)//undefined
  1. 使用Symbol值作为key的属性名 在遍历obj时Object.keys等中是获取不到这些Symbol值
console.log(Object.keys(obj)); // ['hobby']
console.log(Object.getOwnPropertyNames(obj)); //  ['hobby']

# 遍历具有Symbol值作为key的属性名的对象

使用Object.getOwnPropertySymbols()函数获取synbol值

const skeys = Object.getOwnPropertySymbols(obj); //[Symbol(), Symbol(), Symbol()]
const skeysValue = [];
for (const skeyItem of skeys) {
    skeysValue.push(obj[skeyItem]);
}
console.log(skeys, skeysValue); //['张三', '18', '男']

注意

Object.getOwnPropertySymbols()函数只能获取到使用symbol函数定义的属性名,不能获取到使用字符串定义的属性名

# 创建两个相同的Symbol值

使用Symbol.for()函数并传入一个相同的描述就可以使两个symbol值在创建时相等

const s8 = Symbol.for("张三");
const s9 = Symbol.for("张三");
console.log(s8 === s9); //true
//Symbol.keyFor()函数 获取symbol值在创建时使用的描述
const key = Symbol.keyFor(s8);
console.log(key); //张三
s10 = Symbol.for(key);
console.log(s9 === s10); //true

# set的基本使用

set和map是es6中新增两种的数据解构
set是一种新增的数据解构,用来保存数据,类似于数组,但和数组的区别是元素不能重复

# 创建set我们需要set构造函数(暂时没有字面量创建的方式)

//通过构造函数创建set解构
const set = new Set();
//向set解构中添加数据 add()方法
set.add(10);
set.add(10);
//不同内存地址
set.add({});
set.add({});
console.log(set); //Set(3) { 10, {}, {} }
const obj = {name: "张三"};
//相同内存地址
set.add(obj);
set.add(obj);
console.log(set); //Set(4) { 10, {}, {}, { name: '张三' } }

注意

在set对象解构中是通过值所在的内存地址来判断是否是相同元素,如上虽然加入了两个{}但由于内存地址不同,set对象认为他们是两个不同的元素

# set应用场景 数组去重

const arr = [2, 5, 6, 3, 2, 2];
const setArr = new Set(arr);
console.log(setArr); //Set(4) { 2, 5, 6, 3 }

// Array.from;()函数将set对象转化为数组
const newArr = Array.from(setArr);
console.log(newArr); //[ 2, 5, 6, 3 ]

//在set对象结构中支持展开运算符
console.log([...setArr]); //[ 2, 5, 6, 3 ]

# set常见属性和方法

# size属性,返回set对象属性个数(对象长度)

const arr = [2, 5, 6, 3, 2, 2];
const setArr = new Set(arr);
console.log(setArr.size);//4

# add()方法 向set对象结构中添加属性

const set = new Set();
//向set解构中添加数据 add()方法
set.add(10);
console.log(set); //Set(1) { 10 }

# delete()方法 删除某个元素

const arr = [2, 5, 6, 3, 2, 2];
setArr.delete(2);
console.log(setArr); //Set(3) { 5, 6, 3 }

注意

delete()方法 形参只支持传入元素,不支持传入索引

# has()方法 判断set对象中是否包含某个元素 返回布尔值

const setArr = new Set([5, 1])
console.log(setArr.has(100));//false
console.log(setArr.has(5));//true

# clear()方法 清空set解构

const setArr = new Set([5, 1])
setArr.clear();
console.log(setArr);//Set(0) {}

# 遍历set解构

# 使用foreach()方法遍历
setArr.forEach((item) => {
    item = item * 2; //10;12;6
    console.log(item);
});
console.log(setArr);//Set(3) { 5, 6, 3 }
# 使用for of遍历set对象
for (let item of setArr) {
    item = item * 3;
    console.log(item); //15;18;9
}
console.log(setArr);//Set(3) { 5, 6, 3 }

注意

在对上述set对象的遍历中 虽然我们手动修改了set元素的值,但最后set值并未改变

# weakSet的使用

和set类似,也是内部元素不能重复的数据结构

# 和set的区别

  1. weakSet中只能存放对象类型,不能存放基础数据类型
  2. weakSet对元素的引用是弱引用 如果没有其他对象对这个对象进行引用 那么gc可以对该对象进行回收

注意

weakSet不能存放基础数据类型

weakSet.add(11); //报错 不能添加基本数据类型
  1. 对对象是一个弱引用
  2. weakSet不能进行遍历

# weakSet常见方法

  • add(value):添加某个元素,返回wekSet对象本身
  • delete(value):从weakSet中删除和这个值相等的元素,返回boolean类型
  • has(value):判断weakSet中是否存在某个元素,返回boolean类型

    注意

    与set不同weakSet没有clear()方法

# weakSet的使用场景

使用场景未知,待完善

# map的基本使用

es6另外新增的一个数据解构是map,用于存储映射关系,相当于对象

# 和对象的区别

  • 对象的key只能是字符串(es6新增了symbol作为了对象的key)
  • 即使使用计算属性名作为对象的key,该计算属性名也会转为字符串,并且覆盖之前相同类型的计算属性名

注意

在对象中不能使用对象作为key

const obj1 = {
    name: "张三",
};
const obj2 = {
    age: 18,
};
const obj3 = {
    [obj1]: "李四",
    [obj2]: 30,
};
console.log(obj3); //{ '[object Object]': 30 }
  • map允许对象或者其他数据类型作为映射关系的key

在map中使用对象作为key

map.set(obj1, "李四");
map.set(obj2, 30);
console.log(map); //Map(2) { { name: '张三' } => '李四', { age: 18 } => 30 }

# map的使用

# 在创建时加入元素

Map(value)中value的值必须是<anonymous>

const map1 = new Map([
    [obj1, "张三"],
    [obj2, 20],
    [1, "aaa"],
]);
console.log(map1); //Map(3) { { name: '张三' } => '张三', { age: 18 } => 20, 1 => 'aaa' }

# map中常见的属性和方法

  • set(key,value)方法 向map中添加元素
  • get(key)方法 获取对应key的元素值
console.log(map1.get(obj1)); //张三
  • has(key)方法 判断该map中是否存在对应key
console.log(map1.has(obj1), map1.has(obj3));//true false
  • delete(key)方法 删除指定的key 返回删除成功或失败的布尔值
const res = map1.delete(obj1);
console.log(res, map1);//true Map(2) { { age: 18 } => 20, 1 => 'aaa' }

  • claer()方法 清除map中所有元素
map1.clear();
console.log(map1);//Map(0) {}

# map的遍历

使用forEach()方法遍历

map1.forEach((item, key) => {
    console.log(key, item);
});
//结果
// { age: 18 } 20
// 1 aaa

使用 for of 遍历

for (const [key, value] of map1) {//使用数组解构
    console.log(key, value);
}
//结果
// { age: 18 } 20
// 1 aaa

# weakMap的基本使用

和map相似的另外一个数据结构称之为weakMap,也是以键值对的形式存在

# 和map的区别

  • weakMap只能使用对象,不接受其他数据类型作为key
  • weakMap的key对对象的引用是弱引用,如果没有其他引用引用这个对象,那么gc可以回收该对象

# in方法的基本使用

in方法用于判断某个属性是否属于某个数组或对象。

# 使用in方法判断数据是否具有某个元素

const arr = [1, 2, 3, 4, 5];
console.log("结果", 2 in arr); //true
console.log("结果", 8 in arr); //false

# 使用in方法判断对象是否具有某个属性

const obj = {
    name: "张三",
    age: 18,
};
console.log("结果", "sex" in obj);//false
console.log("结果", "name" in obj);//true

# 使用in方法判断构造函数继承的属性

function objFun() {
    this.name = "张三";
}

const obj = new objFun();
console.log("结果", "age" in obj); //false
console.log("结果", "name" in obj); //true
objFun.prototype.age = 18;
console.log("结果", "age" in obj); //true
//判断是否为该对象的自有属性
//对象原型上的属性不会检测
console.log("结果", obj.hasOwnProperty("age")); //false
console.log(obj); //{name:'张三'}

注意

in方法不管是对象的自有属性还是原型链上的继承属性都会被检测, 可以使用对象的hasOwnProperty()方法检测该属性是否是自有属性

# Es7 includes方法

include()方法用于判断数组或字符串中是否包含某一个值
在es7之前可以使用indexOf()方法判断数组中是否包含某一个值

//indexOf(value)方法 获取value值所在数组的索引,如果数组项存在则返回索引值,若不存在则返回-1
const arr = [10.3, 5, 3, 5, 6, 40, 59];
//在es7之前使用indexOf判断
console.log(arr.indexOf(3), arr.indexOf(4));//2 - 1;

# 使用includes()方法 返回布尔值

语法:array.includes(判断的项,从第几项开始判断(默认从第0项))

# 判断数组

const arr = [10, 5, 3, 5, 6, 40, 59];
console.log(arr.includes(8))//false
console.log(arr.includes(10));//true
console.log(arr.includes(10, 2));//false

注意

与indexOf方法不同的是 indexOf方法不能判断NaN

const arr1 = [NaN, undefined];
console.log(arr1.indexOf(NaN)); // -1
console.log(arr1.indexOf(undefined)); // 1

console.log(arr1.includes(NaN));//true
console.log(arr1.includes(undefined));//true
true

# 判断字符串

const str = "hello word!";
console.log(str.includes("word")); //true
console.log(str.includes("123")); //false

# Es7 指数运算符

在es7之前使用Math.pow(底数,指数)来获取指数值

console.log(Math.pow(2, 4)); //16

# es7中的指数运算符**

console.log(2 ** 4);//16

# Es8 对象的value值获取

在es8之前已经有了`object.keys(obj)方法 用于获取对象的所有key 返回该对象key的数组

const obj = {
    name: "张帆",
    age: 18,
    sex: "男",
};
console.log(Object.keys(obj));//[ 'name', 'age', 'sex' ]

# Object.values()方法的使用

Object.values()方法不单单可以传入对象,还可以传入数组、字符串等

# 传入对象 返回对象所有的value值的数组

console.log(Object.values(obj));//[ '张帆', 18, '男' ]

# 传入数组 返回数组本身

const arr = [1, 2, 4];
console.log(Object.values(arr));//[ 1, 2, 4 ]

# 传入字符串 返回字符串所有字符的数组

const str = "123";
console.log(Object.values(str)); //[ '1', '2', '3' ]

# Es8 对象或数组entries键值对的获取

语法:Object.entries(obj|arr)

# 传入对象

const obj = {
    name: "张帆",
    age: 18,
    sex: "男",
};
console.log(Object.entries(obj));//[ [ 'name', '张帆' ], [ 'age', 18 ], [ 'sex', '男' ] ]

# 传入数组

const arr = ["张三", "李四"];
console.log(Object.entries(arr)); //[ [ '0', '张三' ], [ '1', '李四' ] ]

# Es8 字符串首位填充方法

# string.padStart()方法 在字符串首部填充

语法:string.padStart(填充使字符串达到几位(必传),使用什么字符串填充(默认填充空格))

const str = "张三";
console.log(str.padStart(15));
console.log(str.padStart(15, "$"));

# string.padEnd()方法 在字符串尾部填充

语法同上

console.log(str.padEnd(15, "$"));//张三$$$$$$$$$$$$$

# 案列 身份证替换

const idNumber = "353453453453453123123";
const lastNum = idNumber.slice(-4);//获取字符串后四位
const res = lastNum.padStart(idNumber.length, "*");
console.log(res);//*****************3123

# Es10 flat的使用

数组的flat()函数 可以对数组进行降维处理
语法:arr.flat(降维深度:number)
flat函数无法对对象进行降维

const nums = [1, [2, 3], [4, [5, 6]], {name: "张三"}];
console.log(nums.flat(1));//[ 1, 2, 3, 4, [ 5, 6 ], { name: '张三' } ]
console.log(nums.flat(2));//[ 1, 2, 3, 4, 5, 6, { name: '张三' } ]

# Es10 flatMap()的使用

flatMap()方法首先使用映射函数映射每一个元素,然后将结果压缩成一个新数组

注意

  • flatMap是先进行Map操作,再进行flat操作
  • flatMap中的flat的映射深度为1

语法:arr,flatMap(callBack,this指向)

const nums = [1, [2, 3], [4, [5, 6]]];
console.log(nums.map((item) => item)); //[ 1, [ 2, 3 ], [ 4, [ 5, 6 ] ] ]
console.log(nums.flatMap((item) => item)); //[ 1, 2, 3, 4, [ 5, 6 ] ]

# Es10 entries格式数组转换为对象

在Es8中可以使用Object.entries(obj)函数将对象转换成entries格式的数组

const obj = {
    name: "张三",
    age: 18,
    sex: "男",
};
console.log(Object.entries(obj));//[ [ 'name', '张三' ], [ 'age', 18 ], [ 'sex', '男' ] ]

在Es10中可以使用 Object.fromEntries(entries)函数将entries格式的数组还原成对象

const obj = {
    name: "张三",
    age: 18,
    sex: "男",
};
const entries = Object.entries(obj);
console.log(Object.fromEntries(entries)); //{ name: '张三', age: 18, sex: '男' }

# 应用场景 地址参数获取

const url = "https://www.baidu.com?name=张三&age=18&sex=男";
const params = url.split("?")[1]; //name=张三&age=18&sex=男
const queryParams = new URLSearchParams(params); //{ 'name' => '张三', 'age' => '18', 'sex' => '男' }
const paramsObj = Object.fromEntries(queryParams); //{ name: '张三', age: '18', sex: '男' }

# Es10 字符串去除首尾空格

在es10之前使用 str.trim()函数同时去除字符串首部和尾部的空格
但Es10 可以选择去除首部或尾部的空格

# str.trimStart()去除首部空格

const str = "     hello word!  ";
console.log(str.trimStart()); //hello word!____

# str.trimEnd()去除尾部空格

const str = "     hello word!  ";
console.log(str.trimEnd()); //______hello word!

# Es11 大整数类型

在Es11之前 js表示和存储一个比较大的数字是不安全的
获取js能表示安全最大的整数

const max = Number.MAX_SAFE_INTEGER;
console.log(max); //9007199254740991
console.log(max + 1);//9007199254740992
//数值不正确
console.log(max + 2);//9007199254740992

# Es11 新增BigInt数据类型

语法:num+n

注意

大数字后的n不能省略

const max = Number.MAX_SAFE_INTEGER;
console.log(9007199254740992n + 10n); //9007199254741002n
console.log(BigInt(max + 2) + 10n); //9007199254741002n

注意

类似 10n+10 这样的操作因为类型不同无法转化 大数字运算都要保证都是大数字类型
BigInt(max + 2) + 10n

# 讲大数字类型转化为普通数字类型

console.log(Number(BigInt(max + 2) + 10n)); //9007199254741002

注意

将大数字类型转化为普通数字类型可能是不安全或者不正确的

# Es11 空值合并运算符

在es11之前我们会用 ||和&&判空赋值

const foo = "123";
console.log(foo || "默认值");//123

const foo = null;
console.log(foo || "默认值");//默认值

const foo = undefined;
console.log(foo || "默认值");//默认值

const foo = 0;
console.log(foo || "默认值"); //默认值

const foo = '';
console.log(foo || "默认值"); //默认值

注意

在逻辑运算符中 null、undefined、0、‘’都表示false
如果我们需要赋值0或者赋值空字符串逻辑运算符就不适用

# 空值合并运算符(??)会明确判断Null和undefined

const foo = "123";
console.log(foo ?? "默认值"); //123

const foo = null;
console.log(foo ?? "默认值"); //默认值

const foo = undefined;
console.log(foo ?? "默认值"); //默认值

const foo = 0;
console.log(foo ?? "默认值"); //0

const foo = "";
console.log(foo ?? "默认值"); //''

const foo = false;
console.log(foo ?? "默认值"); //false

const foo = true;
console.log(foo ?? "默认值"); //true

# Es11 可选链

可选链是Es11中新增的一个特性
主要作用是让我们的代码在进行null和undefined判断时更加清晰和简洁
当然也可也以在对null和Undefined的属性或方法获取时防止控制台报错

在es11 可选链之前我们可能会用if判断值是否存在

const obj = {
    name: "张三",
    age: 16,
    sex: "男",
};
if (obj.age && obj.age.height) {
    console.log(obj.age.height);
}

# 可选链的使用

如果判断问号前面的值为null或undefined 问号后面的代码不执行 直接返回undefined

const obj = {
    name: "张三",
    age: 16,
    sex: "男",
};
//获取一个不存在的属性
console.log(obj.age?.height); //undefined 控制台不报错

# Es11 获取全局对象标准化

在浏览器环境中 全局对象为window
在node环境中 全局对象为global
在小程序中 全局对象为wx或uni
es11 之前获取相应的全局对象就需要争对对应环境 如在node环境下获取window报错

# globalThis的使用

globalThis会根据当前运行的环境返回该环境对应的全局对象

console.log(globalThis);
//node 环境下获取到的是global对象
//浏览器环境下获取到的是 window对象

# Es11 for in 标准化

在es11之前for in循环对象 不同浏览器赋值的item可能是key或者value
es11 之后ecma规定 for in 循环对象的item 赋值对象的key

const obj = {
    name: "张三",
    age: 15,
    sex: "男",
};
for (const item in obj) {
    console.log(item);
}

# Es12 FinalizationRegistry构造函数

FinalizationRegistry构造函数用于监听某个变量被GC回收 该构造函数可以参入一个回调函数
Gc并不是实时回收

let obj = {
    name: "张三",
    age: 15,
    sex: "男",
};
const finalRegistry = new FinalizationRegistry((value) => {
    console.log("某个对象被销毁了", value);
});
finalRegistry.register(obj, 'obj');
obj = null;

# 逻辑赋值运算符

  1. ||=逻辑或赋值运算
  2. &&=逻辑与赋值运算
  3. ??=逻辑空赋值运算

# Es12 逻辑赋值运算符的使用

let value = false;
value ||= "123"; //123
console.log(value);
// 相当于
value = value || '123'


let value = 0;
value ??= "123";
console.log(value); //0

let value = false;
value ??= "123";
console.log(value); //false

let value = null;
value ??= "123";
console.log(value);//123

注意

逻辑空值运算符只判断null和undefined

# Es13 数组或字符串的at()方法

const arr = [1, 2, 3]
//获取数组最后一项
arr.at(-1)//3
const str = 'hello'
str.at(-1)//o

# Es13 hasOwn()方法

hasOwn()方法用于判断对象中是否存在某一个属性 返回布尔值

const obj = {name: '张三'}
console.log(obj.hasOwn(obj, name))//true
console.log(obj.hasOwn(obj, age))//false
上次更新: 4/25/2024, 3:42:57 PM