关于es6版本
广义的es6指的是2015年发布es6之后的新版本,更细的划分:2015 es6 2016 es7 2017 es8 2018 es9 2019 es10 2020 es11
1.数值扩展
1).Number.isNaN与isNaN的区别
Number.isNaN不存在类型转换的行为,而isNaN会尝试将参数转换为Number类型。isNaN只是判断传入的参数是否能转换为数字,并不是严格的判断是否等于NaN数值;而Number.isNaN判断传入的参数是否严格等于NaN这个数值。
参考: js中isNaN和Number.isNaN的区别是什么
2).Number.isInteger 判断是否是个整数
Number.isInteger(5) // true
Number.isInteger(2.5) // false
3).Math.trunc 把小数部分抹掉
Math.trunc(1.666)
4).Math.sign 检测一个数是正数、0还是负数
如果是正数返回1,如果是0返回0,如果是负数返回-1,不是数字 NaN
Math.sign(-100); //-1
Math.sign(0); // 0
Math.sign(100); // 1
Math.sign('hello'): //NaN
5)Number.EPSILON 误差检查函数
Number.EPSILON 属性表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。 如果浮点数的计算误差能够小于 Number.EPSILON ,我们就可以认为得到了正确结果, Number.EPSILON的实质是一个可以接受的误差范围
0.1 + 0.2 // 0.30000000000000004,并非预期的0.3,那与0.3判断相等肯定是不相等
0.1+0.2 - 0.3 // 5.551115123125783e-17,计算之后的值并非为 0.00000000000000004,因为浮点数要进行转换再计算
(0.1+0.2 - 0.3) < Number.EPSILON // true
Number.EPSILON == Math.pow(2,-52) // true
Number.EPSILON == 1/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2/2 // true
2.对象方法的扩展
1).Object.is 判断两个值是否完全相等
类似===,并且可以判断NaN
Object.is(100,101) // false
Object.is(100,100) // true
Object.is(NaN,NaN) // true
更多使用细节可以参考: MDN - Object.is()
2).Object.assign 对象的合并
一般用于初始化数据的时候的传参覆盖对象,后面的参数把第一个参数覆盖,并返回第一个参数最后的值
var hello = {
hello: 'hello'
}
var world = {
world: 'world',
hello:'hello 2021'
}
Object.assign(hello,world)
// 返回 {hello: "hello 2021", world: "world"}
// 此时的 hello 就是刚刚返回的值
console.log(hello);
// {hello: "hello 2021", world: "world"}
3)Object.setPrototypeOf 和 Object.getPrototypeOf 设置和获取原型
将后面的对象参数给设置为前面参数的原型,设置后前面参数可以访问后面参数的属性
var a = {
hello : 'hello'
}
var b = {
world: 'world'
}
console.log(a);
// {hello: "hello"}
Object.setPrototypeOf(a,b)
console.log(a);
// {hello: "hello"}hello: "hello"__proto__: world: "world"__proto__: Object
console.log(a.world) //就可以拿到b对象的属性了
// world
console.log(Object.getPrototypeOf(a)); // 获取原型
// {world: "world"}world: "world"__proto__: Object
推荐用Object.create设置原型:a = Object.create(b)
3.模块化
1).html中通过script标签
指定类型 type = "module"可以使用js的模块化,如果是引入js文件在js文件中使用模块化,也是要用script指定type的
2).export 暴露数据有好几种方法
分别暴露:在想导出的变量或函数前写 export
export let hello = "hello";
export function world(){
console.log("world");
}
统一暴露
hello = "hello";
function world(){
console.log("world");
}
export {
hello,
world
}
默认暴露
export default {
hello: "hello",
world: function(){
console.log("world");
}
}
3).import 引入
import * as data from '某.js'
就可以使用 data.hello 或 data.world,用as的方式default导出会多一层,要用 data.default.hello 调用
默认暴露方式可以用简便方式,这样不用as取别名就不用多一层嵌套了,只支持默认暴露
import data from '某.js'
解构赋值形式的导入
import {hello,world} from '某.js'
// 默认方式的解构,要取别名
import {default as data} from '某.js'
这时就可以在局部作用域直接使用hello和world变量了,如果已被声明使用的变量,可以通过as取别名
import {hello as newHello,world} from '某.js'
4).babel可以将比较新的es6代码转换为es5
安装工具 babel-cli babel-preset-env browserify
npm i babel-cli babel-preset-env browserify -D
npx可以临时使用babel
npx babel src/js -d dist/js --presets=babel-preset-env
用了babel之后还是require语法,浏览器还是不识别还需要再打包一次
npx browserify dist/js/app.js -o dist/bundle.js
在浏览器直接引用bundle.js就可以使用转换为的es5代码了
5)用npm安装jquery使用jquery模块
npm i jquery -D
js中使用
import $ from 'jquery'
$('body').css('background','pink');
导入完后还需要再转化为es5浏览器才可以渲染
4.es7的新特性
1)includes判断数组中是否包含某个值
比indexOf更方便,直接返回布尔类型的值
let arr = [1,2,3,4];
arr.includes(1); //true
arr.includes(5); //false
2)**幂运算,相当于Math.pow
2 ** 10 // 2的十次方 1024
Math.pow(2,10) //2的十次方 1021
5.await和async
async和await两种语法结合可以让异步代码像同步代码一样
1)async
在函数前使用async,async函数返回值为promise,promise对象结果由async函数执行的返回值决定
async function fn(){
return 'hello world' //返回的不是promise的一般会转化为promise而且成功状态
// return; //不返回值也会转化为promise且成功状态
// return throw new Error(); // 抛出错误的话,会返回promise且失败的结果
// return Promise.resolve(); //返回成功fulfilled的promise
// return Promise.reject(); //返回失败rejected的promise
}
2)await
必须要用在async函数内部,但async函数内不一定需要await
成功则直接使用返回值,失败要用try catch来获取失败的返回值
async function hello(){
return Promise.resolve('hello');
// return Promise.reject('some error')
}
try{
let h = await hello();
}catch(err){
console.log(err);
}
6.对象
1)Object.keys 获取对象的所有键名的数组
2)Object.values 获取对象的所有值的数组
3)Object.entries 获取对象的键名和值的二维数组
var hello = {name:'hello',age:18}
Object.entries(hello);
//会得到二维数组,子数组中第1个位置是键名,第二是值
(2) [Array(2), Array(2)]
0: (2) ["name", "hello"]
1: (2) ["age", 18]
Object.fromEntries 是将二维数组转化为对象
Object.fromEntries([['age','18'],['string','hello']])
// {age: "18", string: "hello"}
4)对象中也可以使用扩展运算符合并几个对象
如果有相同的键的话,后面的将覆盖前面的
let a = {name:'hello',area:'china'}
let b = { age: 18,area:'shanghai'}
let c = {...a,...b}; //{name:'hello',age:18,area:'shanghai'}
7.正则扩展
1).exec 可以进行命名分组(es9)
用(?<组名>某规则),拿取在结果有个groups属性,result.groups.组名就可以了,只通过括号的方式就没有组名
var a4= /(?<number>\d)/g;
console.log(a4.exec('4.ddd'));
//匹配结果中的group可以通过组名调用
(2) ["4", "4", index: 0, input: "4.ddd", groups: {…}]
0: "4"
1: "4"
groups:
number: "4"
index: 0
input: "4.ddd"
2)反向断言
正向断言:可以根据当前后边的内容去判断前面的内容是否符合条件 (?=某规则) 这里的括号只是作判断不分组
反向断言:根据前面的内容去判断 (?<=某规则),这里的括号也只是判断不分组
3).dotAll模式
就是新增s修饰模式,/./s 此时的.可以匹配任意字符,不用这个模式时,.一般是匹配除了换行符之外的任何字符。
8.trimStart和trimEnd分别清楚左侧和右侧空白
" hello".trimStart() // "hello"
"world ".trimEnd() // "world"
trim则会对左右两侧的空白都清除
" hello world ".trim() // "hello world"
9.flat和flatMap
flat是将二维数组转为一维数组,也可以把多维数组转低维,传递一个深度参数,参数为数字,代表转几层
[1,[2,3,4]].flat(); // [1, 2, 3, 4]
[1,[2,[3,4]]].flat(2); // [1, 2, 3, 4]
flatMap跟数组的map方法类似,只是多了flat的功能,返回结果如果是多维数组通过flatMap就变成低维数组了
[1,2,3,4].flatMap(item=>[item*10]);
// [10, 20, 30, 40]
10.获取symbol的description
let s = Symbol('描述信息');
s.description; // 描述信息
11.类的私有属性
只能在类的内部使用,声明时前面可以加#,使用时也带上#
class hello{
#name="hello world";
constructor(){
console.log('调用私有属性',this.#name)
}
}
console.log(new hello())
12.Promise.allSettled和Promise.all
都是批量处理异步任务的,参数通过数组传递,allSettled会返回一个成功的promise结果,里面的内容才是每个异步自己的promise结果
而all是所有成功才返回成功的promise结果,有一个失败则返回失败,失败的信息是这个失败的异步任务的结果信息
var time1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('恭喜,成功')
},1000);
});
var time2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('抱歉,失败了')
},1000)
});
console.log(Promise.allSettled([time1,time2]));
console.log(Promise.all([time1,time2]));
13.matchAll方法匹配正则
matchAll全局匹配正则返回一个迭代对象,而且每个结果都有详细的组的一些信息,match全局匹配则没有
console.log([...("hello").matchAll(/l/g)])
match的方式
console.log([...("hello").match(/l/g)])
14.可选链操作符
对象多层判断父级存在再调用子级的属性时,可以通过可选链式操作符 某对象?.某属性,这样就少写一些先判断父级再判断子级存不存在获取值的代码了
function main(config){
let name = config?.db?.name;
console.log('通过传值获取到的name',name);
}
console.log(
main({
db:{
name: 'localhost'
}
})
)
// 通过传值获取到的name localhost
console.log(main());
// 通过传值获取到的name undefined
结合数组的filter使用?.:
// 选中数组的对象元素中有isSelect属性为true的第1个元素,而且取address属性值
address = this.addressList.filter(item => item.isSelect)[0]?.address;
15.动态import
不是在js顶部统一导入,而是在js代码块按照需要来进行导入,会返回一个promise对象,promise是导入的结果
<script type="module">
// import * as all from './dynamicImport.js';
import('./dynamicImport.js').then(module=>{
console.log(module)
})
</script>
16.globalThis绝对全局对象
在浏览器中是指向window,在node环境是指向node
window:
node:
console.log('全局对象', globalThis);
注意事项
结构赋值时,如果来源的值是undefined或者没声明,都不会覆盖设置的默认值
var {a='hello'} = {
a: undefined
}
console.log(a) // "hello"
var {a='hello'} = {
b: 'world'
}
console.log(a); // "hello"