ES系列新规范
基础回顾:
//作为一个函数使用
let fn1= function(a){
console.log(a);
}
fn1(5);
// 等同于上面的
function fn(a){
console.log(a)
}
fn(9);
//对象里面定义函数
let meth={
fn2: function(a){
console.log(a);
}
}
meth.fn2(3);
1.变量的解构赋值
定义:.ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。(代码更加简洁)
注意:解构的名字必须对应一致;也可解构部分;解构类型必须一样
数组解构
const F4 = ['小沈阳','刘能','赵四','宋小宝'];
let [xiao, liu, zhao, song] = F4;// 相当于我声明了四个变量 这四个变量的值分别是数组相应位置的值
console.log(xiao);// 小沈阳
对象的解构
const zhao = {name: '赵本山',age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
let {name, age, xiaopin} = zhao;
console.log(name);
console.log(xiaopin);
xiaopin();
2.模板字符串
ES6 引入新的声明字符串的方式:`` (反引号)在ES6之前声明字符串有两种方式:’'和""
2.1作用:内容中直接可以换行,其他引号会报错
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
2.2字符串的拼接${变量名}另一个要拼接的字符串
在ES6前 字符串拼接用+
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
3.对象的简化写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁
当属性名和变量名一致时 可以用es6新写法 ;对于方法也可以省略写例如:improve(){}等效于improve:function(){}
let name = '尚硅谷';
let change = function(){
console.log('我们可以改变你!!');
}
/*
完整的写法应该是:
const school = {
name: name,
change: change,
improve: function(){
console.log("我们可以提高你的技能");
}
}
*/
//当属性名和变量名一致时 可以用es6新写法 对于方法也可以省略写
const school = {
name,
change,
improve(){
console.log("我们可以提高你的技能");
}
}
4.箭头函数
4.1声明及特点
1.声明
//声明一个函数
// let fn = function(){}// 以前定义函数的方法
let fn = (a,b) => {// (这里写形参)
return a + b;// 函数体的语法不变
}
//调用函数
let result = fn(1, 2);
2.this 是静态的.,this 始终指向函数声明时所在作用域下的 this 的值(也就是说后期不可以改变)–重点
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '尚硅谷';
const school = {
name: "ATGUIGU"
}
//1.直接调用
// getName();// window
// getName2();// window
//2.call 方法调用(call 方法可以修改里面的值)
// getName.call(school);// ATGUIGU(动态的)
// getName2.call(school);// 尚硅谷(静态的)
3.不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me);//直接报错
4.不能使用 arguments(该变量用来保存实参的) 变量
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
5.箭头函数的简写—重点哦
① 省略小括号, 当形参有且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(9));
②省略花括号, 当代码体只有一条语句的时候, 此时 return 也必须省略;而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8));
4.2案例
①点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
--------------------
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
let _this = this;
//定时器
setTimeout(function(){// 匿名函数的this指向window而非ad ,所以需要在上面先保存指向ad的this
_this.style.background = 'pink';
}, 2000);
});
es6新写法
//绑定事件
ad.addEventListener("click", function(){
//定时器
setTimeout(() => {// 这个箭头函数的this指向在声明时箭头函数所在作用域的this(因为箭头函数的this是静态的)
this.style.background = 'pink';
}, 2000);
});
②从数组中返回偶数的数组
const arr = [1,6,9,10,100,25];
const result = arr.filter(function(item){
if(item % 2 === 0){
return true;
}else{
return false;
}
});
es6新写法
// const result = arr.filter(item=>{
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// })
// 进一步简写
const result = arr.filter(item => item % 2 === 0);
console.log(result);
总结:箭头函数适合与 this 无关的回调、定时器、数组的方法回调
箭头函数不适合与 this 有关的回调、事件回调、对象的方法(只是不适合,并非不能用)
5.允许给函数参数赋初始值
①形参初始值可以有默认值的参数, 一般位置要靠后(潜规则)
function add(a,b,c=3) {
return a + b + c;
}
let result = add(1,2);
console.log(result);//返回值:6
②与解构赋值结合
//名字必须一致
function connect({host="127.0.0.1", username, port}){
console.log(host)
console.log(username)
console.log(port)
}
connect({
username: 'root',
port: 3306
})
6.rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
ES5 获取实参的方式:(获取的类型是对象)
function date(){
console.log(arguments);
}
date('白芷','阿娇','思慧');
rest 参数:(获取的类型是数组,其中args是自定义命名)
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
rest 参数必须要放到参数最后:(进行依次匹配后,将剩余数值全部储存在args里面)
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);//[3,4,5,6]
}
fn(1,2,3,4,5,6);
7.拓展运算符【…】
扩展运算符能将『数组』转换为逗号分隔的『参数序列』(简单理解就是把数组的方括号去掉)
案例:
1.数组的合并
const aa= ['王太利','肖央'];
const bb= ['曾毅','玲花'];
//注释掉的是es5的合并方法
//const cc= aa.concat(bb);
const cc= [...aa, ...bb];
console.log(cc);//['王太利','肖央','曾毅','玲花']
2.数组克隆
const aa= ['E','G','M'];
const bb= [...aa];
console.log(bb);// ['E','G','M']
3.将伪数组(类似对象)转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);
8.Symbol 数据类型
1.描述:
Symbol是ES6引入的一种新的数据类型;
用来表示独一无二的值;
他是一种类似于字符串的值,保证值是唯一的;
Symbol值不能参与任何一种运算,外部也看不到Symbol的值是多少, 只能知道分别定义两个Symbol一定是不同的
2.回顾js数据类型(7个):
USONB(你是如此的牛掰)------口诀,哈哈哈哈
u--undefined
s--string 、symbol
o--object
n--null 、number
b--boolean
3.创建:
let s = Symbol(); // 不用写new 因为是js的默认数据类型
console.log(s,typeof s); // Symbol() symbol
//这里只是给加了一个注释
let s1=Symbol("小白");
let s2=Symbol("小白");
console.log(s1===s2);//false 只是注释,指向地址不一样
//Symbol.for创建
let s1 = Symbol.for("Liu");
let s2 = Symbol.for("Liu");
console.log(s1===s2) // true
注意:不可以与其他数据进行运算
4.作用:给对象添加属性和方法
第一种添加方式
第二种添加方式
9.遍历器
迭代器是一种接口,各种数据结构只要在定义了Iterator接口,就可以完成迭代(循环)操作
ES6加入了新的遍历方式 for-of , 调用Iterator接口对对象进行遍历
数组循环例子:
const tfboys = ["易烊千玺","王源","王俊凯"];
//es5循环
for (var i = 0; i < tfboys.length; i++) {
console.log(tfboys[i]);//易烊千玺 王源 王俊凯
}
//es6循环for-of
for(var v of tfboys){
console.log(v);//易烊千玺 王源 王俊凯
}
//for-in循环
for(var v in tfboys){
console.log(v);//0 1 2
}
对象遍历例子(也可以使用下面ES8中的对象方法的拓展来进行遍历):
const obj = {"name":"易烊千玺",age:"20",sex:"男"};
obj[Symbol.iterator] = function(){
var keys = Object.keys(this);
var count = 0;
return {
next(){
if(count<keys.length){
return {value: obj[keys[count++]],done:false};
}else{
return {value:undefined,done:true};
}
}
}
};
for(var v of obj){
console.log(v);//易烊千玺 20
}
//for in 遍历
const tfboys = {name:"易烊千玺",age:"20",sex:"男"};
for(var v in tfboys){
console.log(v);//name age sex
console.log(tfboys[v]);//易烊千玺 20 男
}
10.promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
11.模块化
优点:防止命名冲突;代码复用;高维护性
也可以使用统一暴露
也可以使用默认暴露
模块化在项中的使用(有些浏览器不支持需要编译):
原因:并非所有的浏览器都支持es6的模块化规范,所以要将文件转换为es5 的规范,要使用Babel编译器进行javascript的编译
安装工具:babel-cli(babel的命令行工具) babel-present-env(预设包,将es最新的js进行转换) browserifty(打包工具,也可以使用webpack)
//1.初始化执行
npm init --yes
//2.安装babel
npm i babel-cli babel-present-env browserify -D
//3.src/js是自己写的文件路径;dist/js编译后的文件路径;presents=babel-preset-env是手动传参,项目中也可以直接传参
npx src/js -d dist/js --presents=babel-preset-env
//4.打包;dist/js/app.js是需要打包的具体文件;dist/bundle.js
打包生成的文件,具体项目中正常引入bundle.js文件就可以
npx browserify dist/js/app.js -o dist/bundle.js
注意:修改js代码后,需要运行3和4的代码,更新
12.ES7新特性
1.includes(是否包含)
用于判断数组中是否包含
案例:
const name=["李四","王五","小白"];
consloe.log(name.includes("淑芬"))//false
//es5中我们使用indexof来判断
consloe.log(name.indexOf("淑芬"))//-1
2.** 幂运算
案例:
console.log(2 ** 3);//8
//es5中写法
console.log(Math.pow(2,3));//8
13.ES8新特性
1.async 和 await的认识
async 和 await两种语法的结合可以让异步代码像同步代码一样
async 的声明
//声明只需要在函数前加一个async
async function fun (){
//不管这里返回什么值,都返回的是promise类型的对象
//return "你好";
return new Promise((resolve,reject)=>{
//resolve("成功数据");
reject("数据失败");
})
}
const result=fun();
console.log(result);//打印的是promise的一个对象
await的使用(用于返回成功的值,主要用于接收结果)
注意:await必须放在async里面,async里面可以没有await
//外部创建一个promise对象
const p = new Promise((resolve,reject)=>{
//resolve("成功数据");
reject("数据失败");
});
async function fun (){
try{
let result = await p;
console.log(result);//打印Promise的具体值,这里是“成功数据”
}catch(e){
console.log(e);//打印Promise的具体值,这里是“数据失败”
}
}
//调用函数
fun();
读取外部文件内容案例,多个文件读取重复如下代码
function study() {
fs.readFile("../es6学习.md", (err, data) => {
if (err) reject(err);
resolve(data);
});
}
async function main() {
let study = await study();//直接打印外部文件的内容
console.log(study.toString());
}
main();
用同步的方法写异步请求(发送ajax请求)案例
// 请求封装
function sendAJAX() {
return new Promise((resolve, reject) => {
// 1.创建对象
const x = new XMLHttpRequest();
// 2.初始化
x.open("GET", url);
// 3.发送
x.send();
// 4.事件绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
//判断状态码
if (x.status >= 200 && x.status < 300) {
//成功时回调
resolve(x.response);
} else {
//失败时回调
reject(x.status);
}
}
};
});
}
// promise then 方法测试
// sendAJAX("http://rap2api.taobao.org/app/mock/293221/manage/user/add")
// .then((value) => {
// console.log(value);
// })
// .catch((err) => {
// console.log(err);
// });
// async与await测试
async function main() {
let result = await sendAJAX(
"http://rap2api.taobao.org/app/mock/293221/manage/user/add"
);
console.log(result);//打印请求的内容
}
2.对象方法扩展(读取键值对)
//声明一个对象
const school = {
name: "硅谷",
subject: ["web", "JAVA", "大数据"],
};
// 获取对象所有键
console.log(Object.keys(school));
// 获取对象所有值
console.log(Object.values(school));
// 获取entries对象,返回值是一个数组,值也是一个数组,一般用来直接封装一个map集合
console.log(Object.entries(school));
// ★ 多用来创建Map
const m = new Map(Object.entries(school));
console.log(m);
3.rest参数
ES6中数组用到了rest参数,到ES8中rest也同样可以用到对象之中
function connect({ host, port, ...user }) {
console.log(host);
console.log(port);
console.log(user);//同样的,是将username和password的值都放在了user中
}
connect({
host: "localhost",
port: "3306",
username: "litterBai",
password: "12345",
});
4.拓展运算符【…】
//同样的,在es8中对象也可以使用拓展运算符
const skillOne = {
q: "吃饭",
};
const skillTwo = {
w: "睡觉",
e: "打游戏",
};
const gavin = { ...skillOne, ...skillTwo };
console.log(gavin);//合并2个对象
14.ES9新特性
1.正则扩展-命名捕获分组
案例: 提取url和[标签文本]
普通提取:
// 声明字符串
let str = "<a href='www.bilibili.com'>b站</a>";
const reg = /<a href='(.*)'>(.*)</a>/;
const result = reg.exec(str);
console.log(result[1]);//www.bilibili.com
console.log(result[2]);//b站
命名捕获分组提取(好处是真实项目中的正则会发生改变,这样只需要命名捕获就可以,不需要修改大量代码):
// 声明字符串
let str = "<a href='www.bilibili.com'>b站</a>";
const reg = /<a href='(?<url>.*)'>(?<text>.*)</a>/;
const result = reg.exec(str);
console.log(result.groups.url);//www.bilibili.com
console.log(result.groups.text);//b站
2.正则扩展-反向断言
案例:(提取“555”标识)
// 声明字符串
let str = "JS12345你知道么555啦啦啦";
// 正向断言
// const reg = /d+(?=啦)/;
// const result = reg.exec(str);
// 反向断言
const reg = /(?<=么)d+/;
const result = reg.exec(str);
console.log(result);
3.正则扩展-dotAll 模式
代替换行符
// dot . 元字符,代表除换行符以外的的任意单个字符
let str = `
<ul>
<li>
<a>肖申克救赎</a>
<p>日期:1998-1-1</p>
</li>
<li>
<a>阿甘正传</a>
<p>日期:1998-1-1</p>
</li>
</ul>`;
// 声明正则
// const reg = /<li>s+<a>(.*?)</a>s+<p>(.*?)</p>/;
const reg = /<li>.*?<a>(?<title>.*?)</a>.*?<p>(?<time>.*?)</p>/gs;
// 执行匹配
// const result = reg.exec(str);
// console.log(result);
let result;
let data = [];
while ((result = reg.exec(str))) {
data.push({ title: result.groups.title, time: result.groups.time });
}
// 输出结果
console.log(data);
15.ES10
1.字符串方法扩展trimStart()清除左侧空格,trimEnd()清除右侧空格
let str = " i am gavin ";
console.log(str);
console.log(str.trim());
console.log(str.trimStart());
console.log(str.trimEnd());
16. ES11新特性
1.class 私有属性
注意:设置私有,只需要在属性前加#
class Person {
name;
// 私有属性
#age;
#weight;
constructor(name, age, weight) {
this.name = name;
this.#age = age;
this.#weight = weight;
}
intro() {
console.log(this.#age);
console.log(this.#weight);
}
}
const girl = new Person("小绿", 12, "50kg");
console.log(girl);
// console.log(girl.#age);
girl.intro();//只能通过方法调用内部私有属性
2.可选链操作符【 ?】
★ 实用,可用来简化判断,当没有传参的时候不至于报错
// ?.
function main(config) {
//传统方式
// const dbHost = config && config.db && config.db.host;
//可选链
const dbHost = config?.db?.host;
console.log(dbHost);
}
main({
db: {
host: "localhost:3000",
username: "root",
},
});
3.绝对全局对象 globalThis
始终指向全局对象,不分场景