ES7知识点解析
01_array-includes方法
const names = ["abc", "cba", "nba", "mba", NaN];
if (names.indexOf("cba") !== -1) {
console.log("包含abc元素");
}
// ES7 ES2016 参数 第一个参数 判断的元素 第二个参数是从数组的第几个索引开始判断
if (names.includes("cba", 2)) {
console.log("包含abc元素");
}
// includes和indexOf的区别
// indexOf没办法正确判断NaN的
if (names.indexOf(NaN) !== -1) {
console.log("包含NaN");
}
// includes正确判断NaN的
if (names.includes(NaN)) {
console.log("包含NaN");
}
02_指数的运算方法
const result1 = Math.pow(3, 3)
// ES7: **
const result2 = 3 ** 3
console.log(result1, result2)
ES8知识点解析
01_Object的values获取
const obj = {
name: "why",
age: 18,
};
// 获取对象的所有的key
console.log(Object.keys(obj));
// 获取对象的所有的values
console.log(Object.values(obj));
const arr = Object.values(obj);
console.log(arr[0]); //why
// 用的非常少
// 传入一个数组 ,获取的是数组本身
console.log(Object.values(["abc", "cba", "nba"])); //['abc', 'cba', 'nba']
// 传入一个字符串,获取的是字符串的每个字符
console.log(Object.values("abc")); //['a', 'b', 'c']
02_Object的entries获取
const obj = {
name: "why",
age: 18,
};
// Object.entries 可以获取到一个数组,数组中会存放可枚举属性的键值对数组。-----
// 传入对象-------以数组的形式,用每个数组来存放对象中可枚举属性的键值对 key还是key value还是value
// console.log(Object.entries(obj)); //[ [ 'name', 'why' ], [ 'age', 18 ] ]
const objEntries = Object.entries(obj);
// forEach
objEntries.forEach((item) => {
// item[0]是键key,item[1]是值value
console.log(item[0], item[1]);
});
// for 方法
for (const en of objEntries) {
// 接受参数key 就是可以 ,value就是obj中的value
const [key, value] = en;
console.log(key, value);
}
// 传入数组 ----------以数组的形式,索引变成key 数组里的元素变成值 用每个数组来存放
// console.log(Object.entries(["abc", "cba", "nba"])); //[ [ '0', 'abc' ], [ '1', 'cba' ], [ '2', 'nba' ] ]
// 传入字符串 ----------以数组的形式,分割每个字符 字符顺序变成key,每个字符值是值 用每个数组来存放
// console.log(Object.entries("abc"));//[ [ '0', 'a' ], [ '1', 'b' ], [ '2', 'c' ] ]
03_padStart和padEnd使用
const message = "Hello World";
// padStart在填充内容之前 两个参数 第一个参数填充到多少个字符长度,第二个参数填充的内容
// padEnd在填充内容之后 两个参数 第一个参数填充到多少个字符长度,第二个参数填充的内容
// 注,如果第一个参数填充到多少个字符长度 的数值小于本字符长度,将不做处理,返回本字符本身
const newMessage = message.padStart(15, "*").padEnd(20, "-");
console.log(newMessage);
// 案例---身份证号码的隐藏 用replace()函数也行
const cardNumber = "321324234242342342341312";
// slice(切片) 也允许参数为负数 这里截取到最后四位 注意: slice (切片) () 方法不会改变原始数组。
const lastFourCard = cardNumber.slice(-4);
// 填充的位数也可以个变量 的属性 只要最后是数字就行
const finalCard = lastFourCard.padStart(cardNumber.length, "*");
console.log(finalCard);
// replace()函数
var phone = "18200002111";
const num = phone.replace(/^(\d{3})\d+(\d{4})$/, "$1****$2");
console.log(num);
04_Trailing-Commas使用
// 在ES8中,我们允许在函数定义和调用时多加一个逗号仅此而已,没啥用
function foo(m, n) {}
foo(20, 30);
05_aysnc的function使用
async/await是什么
async/await 是ES7提出的基于Promise的解决异步的最终方案。
async
async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async函数可以直接then,返回值就是then方法传入的函数。
// async基础语法
async function fun0(){
console.log(1);
return 1;
}
fun0().then(val=>{
console.log(val) // 1,1
})
async function fun1(){
console.log('Promise');
return new Promise(function(resolve,reject){
resolve('Promise')
})
}
fun1().then(val => {
console.log(val); // Promise Promise
})
await
await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。
await 修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;
如果不是Promise对象:把这个非promise的东西当做await表达式的结果。
async function fun(){
let a = await 1;
let b = await new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('setTimeout')
},3000)
})
let c = await function(){
return 'function'
}()
console.log(a,b,c)
}
fun(); // 3秒后输出: 1 "setTimeout" "function"
function log(time){
setTimeout(function(){
console.log(time);
return 1;
},time)
}
async function fun(){
let a = await log(1000);
let b = await log(3000);
let c = log(2000);
console.log(a);
console.log(1)
}
fun();
// 立即输出 undefined 1
// 1秒后输出 1000
// 2秒后输出 2000
// 3秒后输出 3000
async/await 的正确用法
// 使用async/await获取成功的结果
// 定义一个异步函数,3秒后才能获取到值(类似操作数据库)
function getSomeThing(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('获取成功')
},3000)
})
}
async function test(){
let a = await getSomeThing();
console.log(a)
}
test(); // 3秒后输出:获取成功
<script>
function requestData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222);
console.log(11);
}, 2000);
});
}
// 1.
// async function foo() {
// const res1 = await requestData();
// console.log("后面的代码1", res1);
// // 执行完加载res1的值才执行res2函数
// const res2 = await requestData(); 等2000后执行
// console.log("res2后面的代码", res2);
// // 执行完加载res2的值才执行res3函数 等4000后执行
// const res3 = await requestData();
// console.log("res3后面的代码", res3);
// }
// 2.
async function foo() {
const res1 = await requestData();
console.log("后面的代码1", res1);
// 执行完加载res1的值同时执行没有await的 res2函数和await有res3函数 只等2000后执行
const res2 = requestData();
const res3 = await requestData();
console.log("res2后面的代码", res2);
console.log("res3后面的代码", res3);
}
// 3.
// async function foo() {
// const res1 = await requestData();
// console.log("后面的代码1", res1);
// // 执行完加载res1的值同时执行res2函数res3函数 等4000后执行
// const res2 = await requestData();
// const res3 = await requestData();
// console.log("res2后面的代码", res2);
// console.log("res3后面的代码", res3);
// }
// 4.
// async function foo() {
// const res1 = await requestData();
// console.log("后面的代码1", res1);
// // 执行完加载res1的值同时执行加载res3函数,会报错
// const res2 = await requestData();
// console.log("res3后面的代码", res3); //index.html:46 Uncaught (in promise) ReferenceError: Cannot access 'res3' before initialization
// const res3 = await requestData();
// console.log("res2后面的代码", res2);
// }
foo();
</script>
ES10知识点解析
01_flat和flatMap的使用
// 1.flat的使用 数组降维 ,不穿默认降维一级 ,传入数字几降级几维,大于数组维度,就显示最低形式
// const nums = [10, 20, [2, 9], [[30, 40], [10, 45]], 78, [55, 88]]
// const newNums = nums.flat()
// console.log(newNums)
// const newNums2 = nums.flat(2)
// console.log(newNums2)
// 2.flatMap的使用
// const nums2 = [10, 20, 30]
// const newNums3 = nums2.flatMap(item => {
// return item * 2
// })
// const newNums4 = nums2.map(item => {
// return item * 2
// })
// console.log(newNums3)
// console.log(newNums4)
// 不使用flatMap
// const messages = ["Hello World", "hello lyh", "my name is coderwhy"];
// const arr = [];
// for (const msg of messages) {
// const msgs = msg.split(" ");
// for (const msg3 of msgs) {
// arr.push(msg3);
// }
// }
// console.log(arr);
// 3.flatMap的应用场景 flatMap会对数组里面的元素进行降维,map不会
const messages = ["Hello World", "hello lyh", "my name is coderwhy"];
const words = messages.flatMap((item) => {
return item.split(" ");
});
console.log(words);
02_Object的fromEntries
// const obj = {
// name: "why",
// age: 18,
// height: 1.88
// }
// 将对象转化成数组 --
// const entries = Object.entries(obj)
// console.log(entries)
// ES6之前写法将数组在转化成对象
// const newObj = {}
// for (const entry of entries) {
// newObj[entry[0]] = entry[1]
// }
// console.log(newObj)
// 1.ES10中新增了Object.fromEntries方法 将数组在转化成对象
// const newObj = Object.fromEntries(entries)
// console.log(newObj)
// 2.Object.fromEntries的应用场景
const queryString = "name=why&age=18&height=1.88";
const queryParams = new URLSearchParams(queryString);
for (const param of queryParams) {
console.log(param);
}
// 将键值对转变成对象Json格式
const paramObj = Object.fromEntries(queryParams);
console.log(paramObj);
03_trimStart和trimEnd使用
const message = " Hello World ";
// 去除字符串首尾空格
console.log(message.trim());
// 去除字符串首部空格
console.log(message.trimStart());
// 去除字符串尾部空格
console.log(message.trimEnd());
ES11知识点解析
01_大整数BigInt的使用
// ES11之前 max_safe_integer
const maxInt = Number.MAX_SAFE_INTEGER;
console.log(maxInt); // 9007199254740991 最大安全的数字
console.log(maxInt + 1); //虽然能表示,但是并不安全
console.log(maxInt + 2);
// ES11之后: BigInt 可以表示大数据的类型这种数字是安全的 数字后面+n
const bigInt = 900719925474099100n;
// 两种类型转换的方式 方式一
console.log(bigInt + 10n); //数字运算必须加上n 类型相同才可以相加只不过之前的有些运算js内部做出了隐式转换
// 两种类型转换的方式 方式二
const num = 100;
console.log(bigInt + BigInt(num));
// 转成小数 --但是如果数字本身过大,是不安全的
const smallNum = Number(bigInt);
console.log(smallNum);
02_Nullish-Coalescing-operator
const foo = undefined;
//逻辑或 如果前面为真,就不在执行后面,如果前面为假,则执行后面 但是有弊端 如果我们传入""空值或者null 默认值也是false 执行后面语句
// const bar = foo || "default value"
// ES11: 空值合并运算 ?? 只有你传入的值是undefined或者null,才会执行后面语句
const bar = foo ?? "defualt value";
console.log(bar);
// ts 是 js 的超级
03_OptionalChaining
const info = {
name: "why",
// friend: {
// girlFriend: {
// name: "hmm"
// }
// }
};
// 如果之前对象点.属性没有的话,会直接报错 后面的代码不在执行
// console.log(info.friend.girlFriend.name)
// if (info && info.friend && info.friend.girlFriend) {
// console.log(info.friend.girlFriend.name)
// }
// ES11提供了可选链(Optional Chainling) 不确定谁有没有的情况下加上可选链 ?.,如果没有也不会报错,而是返回为undefined
console.log(info.friend?.girlFriend?.name);
console.log("其他的代码逻辑");
04_获取全局对象globalThis
// 获取某一个环境下的全局对象(Global Object)
// 在浏览器下获取环境下的全局对象
// console.log(window)
// console.log(this)
// 在node下获取环境下的全局对象
// console.log(global)
// ES11 不管是浏览器还是node都可以通过globalThis获取环境下的全局对象
console.log(globalThis);
05_for-in操作的标准化
// for...in 标准化: ECMA
const obj = {
name: "why",
age: 18,
};
// for in遍历对学校的时候 item是key
for (const item in obj) {
console.log(item);
}
ES12知识点解析
01_finalizationRegistry
// ES12: FinalizationRegistry类
// FinalizationRegistry类在对象销毁前执行
const finalRegistry = new FinalizationRegistry((value) => {
console.log("注册在finalRegistry的对象, 某一个被销毁", value);
});
let obj = { name: "why" };
let info = { age: 18 };
// 注册 两个参数第一个参数注册到那个对象,第二个参数,自定义传入值 回调函数中的参数value会接收
finalRegistry.register(obj, "obj");
finalRegistry.register(info, "value");
// GC垃圾回收并不是实时的,而是更具js内部的一些算法进行回收
// 销毁对象
obj = null;
info = null;
02_WeakRef的使用
// ES12: WeakRef类
// WeakRef.prototype.deref:
// > 如果原对象没有销毁, 那么可以获取到原对象
// > 如果原对象已经销毁, 那么获取到的是undefined
const finalRegistry = new FinalizationRegistry((value) => {
console.log("注册在finalRegistry的对象, 某一个被销毁", value);
});
let obj = { name: "why" };
// WeakRef创建一个弱引用 GC不过弱引用有没有指向,依然会被销毁
let info = new WeakRef(obj);
finalRegistry.register(obj, "obj");
obj = null;
setTimeout(() => {
// deref()获取原来对象
console.log(info.deref()?.name);
console.log(info.deref() && info.deref().name);
}, 10000);
03_logical-assign-operator
// 1.||= 逻辑或赋值运算
// let message = "hello world";
// message = message || "default value"
// 上面代码的简写 如果message有值,就赋值message本身的值,没值就写入默认值
// message ||= "default value";
// console.log(message);
// 2.&&= 逻辑与赋值运算
// &&
// const obj = {
// name: "why",
// foo: function() {
// console.log("foo函数被调用")
// }
// }
// 如果obj.foo存在则执行&& 后面的代码obj.foo()
// obj.foo && obj.foo()
// &&=
// let info = {
// name: "why"
// }
// 1.判断info
// /2.有值的情况下, 取出info.name
// info = info && info.name
// 简写 很少用,可读性差
// info &&= info.name
// console.log(info)
// 3.??= 逻辑空赋值运算
// let message = 0
// message ??= "default value"
// console.log(message)
_ES13知识点解析
01_at方法
const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr.at(-1));
var str = "Hello world!";
console.log(str.at(1));
console.log(str.at(-1));
02_对象属性hasOwn
const obj = {
name: "why",
age: 18,
// 1.和hasOwnProPerty的区别一、防止对象也要一个自己的hasOwnProperty()方法
hasOwnProperty: function () {
return "abc";
},
__proto__: {
address: "广州市",
},
};
console.log(obj.name, obj.age);
console.log(obj.address);
console.log(obj.hasOwnProperty("name")); //true
console.log(obj.hasOwnProperty("address")); //false 原型上存在也返回false,不过可以定义到obj对象属性上
console.log(Object.hasOwn(obj, "name")); //true
console.log(Object.hasOwn(obj, "address")); //false 原型上存在也返回false,不过不可以定义到obj对象属性上
// 原型对象指向null,就是没有
const info = Object.create(null);
info.name = "why";
console.log(info.hasOwnProperty("name")); // 报错 在内存中有个info对象它的隐式原型对象指向null,自己原型执行null。没有hasOwnProperty方法,之前可以通过原型指向Object,Object原型上有hasOwnProperty
console.log(Object.hasOwn(info, "name")); //true
03_class中新的成员属性
class Person {
// 1.实例属性
// 对象属性 :public 公共-》 public instance fields
height = 1.88;
// 对象属性 :private 私有:程序员之间的约定 --但是如果真的访问还是可以访问
// _intro = "name is why"
// ES13对象属性:private 私有:不可以访问,只能class里面访问使用
#intro = "name is why";
// 2.类属性(static)
// 类属性 :public
static totalCount = "70亿";
// 类属性 :private
static #maleTotalCount = "70亿";
constructor(name, age) {
// 对象中的属性:在constructor 通过this设置
this.name = name;
this.age = age;
this.address = "广州市";
}
// 3.静态代码块 在加载类的时候执行静态代码块,只执行一次--一般进行初始化操作
static {
console.log(1111);
console.log("111");
}
}
const p = new Person("why", 18);
console.log(p);
// console.log(p.name,p.age,p.address);
// console.log(p.name,p.age,p.address,p.#intro);
// console.log(Person.#maleTotalCount); //私有访问不到