ES7
includes
const names = ["abc", "cba", "nba", "mba", NaN];
if (names.indexOf("abc") !== -1) {
console.log("包含abc")
}
if (names.indexOf(NaN) !== -1) {
console.log("包含NaN"); //不会打印
}
if (names.includes(NaN)) {
console.log("包含NaN"); //会打印
}
if (names.includes("abc")) {
console.log("包含abc")
}
指数运算
const result1 = Math.pow(3,3);
// ES7
const result2 = 3 ** 3;
ES8
Object.values
之前可以通过Object.keys获取对象(不包括原型)中所有的key,在ES8中提供了Object.values()来获取所有的values。
const obj = {
name: "zhangsan",
age: 18,
address: [1, 2, 3, 4, 5],
friends: {
a: 1,
b: 2,
c: 3
}
}
console.log(Object.keys(obj));
console.log(Object.values(obj));
entries
通过Object.entries 可以获取到一个数组,数组中会存放可枚举属性的键值对数组
const obj = {
name: "zhangsan",
age: 18,
address: [1, 2, 3, 4, 5],
friends: {
a: 1,
b: 2,
c: 3
}
}
Object.defineProperty(obj, "name", {
configurable: true,
enumerable: false,
writable: true,
value: "999"
})
// [["age","18"],["address",[1,2,3,4,5]],["friends",{a:1,b:2,c:3}]]
console.log(Object.entries(obj))
String Padding
某些字符串我们需要对其进行前后的填充,来实现某种格式化效果,ES8中增加了 padStart 和 padEnd方法,分别是对字符串的首尾进行填充的。
我们简单举一个应用场景:比如需要对身份证、银行卡的前面位数进行隐藏:
// 银行卡号
var cardNumber = "23237532458972345234";
// 保留后4位
var lastFourNumber = cardNumber.slice(-4);
// 显示最后4位,前面显示*
var finalCard = lastFourNumber.padStart(17, "*")
console.log(finalCard)
日期填充案例
var date = new Date();
var year = date.getFullYear();
// 不满2位补充0
var month = (date.getMonth() + 1).toString().padStart(2, '0');
// 不满2位补充0
var day = (date.getDate()).toString().padStart(2, '0')
console.log(year, month, day)
Object Descriptors
Object.getOwnPropertyDescriptors()用来获取一个对象的所有自身属性的描述符。
const obj = {
name: "zhangsan",
age: 18
}
Object.defineDescriptors(obj)
ES10
flat
方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
const nums = [10, 20, [2, 9], [[30, 40], [10, 45]], 78, [55, 88]]
const flatArr = (arr) => {
return arr.reduce((prev, cur) => {
return prev.concat(Array.isArray(cur) ? flatArr(cur) : cur)
}, [])
}
// ES10之前
console.log(flatArr(nums))
// flat
console.log(nums.flat(Infinity))
flatMap
首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。
- flatMap是先进行map操作,再做flat的操作;
- flatMap中的flat相当于深度为1;
const message = ["Hello World", "你好啊 李银河", "my name is why"];
const msg1 = message.map(item => {
return item.split(' ')
})
// [["Hello", "world"], ["你好啊", "李银河"], ["my", "name", "is", "why"]]
const msg2 = message.flatMap(item => {
//先map 然后flat 深度为1
return item.split(' ')
})
console.log(msg1, msg2)
fromEntries
const obj = {
a: 1,
b: 2,
c: 3
}
// 对象转成entries ---> 遍历
const entries = Object.entries(obj)
entries.forEach(entry => {
console.log(entry[0], entry[1])
})
// 对象转成entries ---> 遍历
for (const [key, value] of entries) {
console.log(key, value)
}
// entries转换成对象 ES10新增
// Object.fromEntries的应用场景
const str = "name=why&age=18&height=1.88"
const params = new URLSearchParams(str)
// 将entries转换为 对象
const paramObj = Object.fromEntries(params)
console.log(paramObj)
trimStart tirmEnd
const message = " Hello World ";
console.log(message.trim());
console.log(message.trimStart());
console.log(message.trimEnd());
ES11
BigInt
在ES11之前大于MAX_SAFE_INTEGER的数值,表示的可能是不正确的。
const maxInt = Number.MAX_SAFE_INTEGER
console.log(maxInt + 1) // 可能表示出来不正确
// ES11之后
const bigInt = 99999999999999999999n;
console.log(bigInt + 10n); //可以正确表示
console.log(typeof bigInt); //bigInt
const num = 10;
// int 和 bigInt运算需要转换
console.log(bigInt + BigInt(num));
// bigInt 和 int运算需要转换
console.log(num / Number(10n));
??空值合并运算符
空值合并操作符,可以在使用可选链时设置一个默认值
const obj = {
friend: {
girlFriend: {
// name: "luck"
}
}
}
// 没有可选链操作符之前
if (obj.friend && obj.friend.girlFriend && obj.friend.girlFriend.name) {
console.log(obj.friend.girlFriend.name)
} else {
console.log(undefined)
}
// 可选链操作符 空值合并运算符
console.log(obj?.friend?.girlFriend?.name ?? "默认值")
// 或者
const foo = undefined; //当值是0 或者 是"" bar1有bug
const bar1 = foo || "default value";
const bar2 = foo ?? "defualt value";
?.可选链操作符
允许读取位于连接对象链深处的属性值,而不必明确验证链中的每个引用是否有效。
const obj = {
friend: {
girlFriend: {
name: "luck"
}
}
}
// 没有可选链操作符之前
if( obj.friend && obj.friend.girlFriend && obj.friend.girlFriend.name ) {
console.log(obj.friend.girlFriend.name)
} else {
console.log(undefined);
}
// 可选链操作符
console.log(obj?.friend?.girlFriend?.name);
Global This
JavaScript环境的全局对象,不同的环境获取的方式是不一样的。
- 比如在浏览器中可以通过this、window来获取
- 比如在Node中我们需要通过global来获取
- ES11中对获取全局对象进行了统一的规范:globalThis
console.log(globalThis);
console.log(this); //浏览器上
console.log(global); //node中
for..in标准化
- 在ES11之前,虽然很多浏览器支持for...in来遍历对象类型,但是并没有被ECMA标准化。
- 在ES11中,对其进行了标准化,for...in是用于遍历对象的key的:
// for...in 标准化: ECMA
const obj = {
name: "why",
age: 18
}
for (const item in obj) {
console.log(item)
}
ES12
FinalizationRegistry
- FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调 用一个清理回调。(清理回调有时被称为 finalizer );
- 可以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值;
// ES12: FinalizationRegistry类
const finalRegistry = new FinalizationRegistry((value) => {
console.log("注册在finalRegistry的对象, 某一个被销毁", value)
})
function newArr() {
return new Array(1024 * 1024).fill(1)
}
//分配20个引用 让其引用保存在数组 不被释放
var arrList = [];
for (var i = 0; i < 20; i++) {
setTimeout(function () {
arrList.push(newArr())
}, i * 100)
}
setTimeout(() => {
for (var i = 0; i < 10; i++) {
//以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值
finalRegistry.register(arrList[i], i)
}
}, 4000)
// 释放10个引用 然后等待GC回收10个引用
// 这里要注意, 释放10个
setTimeout(function () {
for (var i = 0; i < 10; i++) {
arrList.shift()
}
}, 5000)
WeakRefs
- 如果我们默认将一个对象赋值给另外一个引用,那么这个引用是一个强引用。如果我们希望是一个弱引用的话,可以使用WeakRef。
// ES12: WeakRef类
// WeakRef.prototype.deref:
// > 如果原对象没有销毁, 那么可以获取到原对象
// > 如果原对象已经销毁, 那么获取到的是undefined
let obj = { name: "why" };
let info = new WeakRef(obj);
// 置空 info是弱引用 会被回收的
obj = null
// 被回收之前 能够打印
console.log(info.deref()?.name)
// 等待GC回收obj 我们再来打印弱引用 info.deref()不存在的话会返回 undefined
// 这里假设是10秒回收,但是具体多久回收 我也不知道
setTimeout(() => {
// 用可选链 + 空值合并
console.log(info.deref()?.name ?? "啥也没有")
// 如果不用可选链
console.log(info.deref() && info.deref().name)
}, 10000)
logical assignment operators
// 1.逻辑或运算符
let message = ""
message = message || "Hello World";
message ||= "Hello World";
// 2.逻辑与操作符
let obj = {
name: "why",
foo() {
console.log('123')
}
}
obj0 = obj && obj.foo;
obj0()
obj &&= obj.name;
// 逻辑空运算符
let foo = null;
foo ??= "默认值"
console.log(foo)