ES6学习笔记
1、let特性
-
变量不能重复声明
let a; let b,c,d; let aaa = 123, bbb = "hello"; let name = "小王"; let name = "小马";//错误,不能重复声明变量
-
块级作用域
{ let name = "小王"; } console.log(name);//错误
-
不存在变量提升
//var可以未声明调用 console.log(name);//输出undefined var name = "小王"; console.log(age);//错误 let age = 21;
-
不影响作用域链
{ let name = "小王"; function abc(){ console.log(name); } } abc();//输出"小王",在函数abc中,没有name变量,会往上一级寻找
2、const
-
声明时一定要指定初始值
const name;//报错 const name = "小王";
-
一般常量使用大写(潜规则)
-
也有块级作用域
-
对于数组和对象的元素的修改,不算对常量的修改,不会报错
3、变量的解构赋值
-
数组的解构
let [a,b,c,d] = ["小王","小马","小丽","小强"];
- 对象的解构
const aaa = { name: "小王", age: 21, eat: function(){ console.log("吃吃吃"); } } //解构 let {name,age,eat} = aaa; //调用 console.log(name);//小王
4、模板字符串
-
声明使用反引号
let name = `小王`; console.log(name);//小王
2.内容中可以直接出现换行符
let ul = `
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
`
3.可以拼接变量(使用${变量名})
let name = "小王";
let age = 21;
let result = `${name}已经${age}岁了!!!`;
console.log(result);//小王已经21岁了
5、对象的简化写法
let name = "小王";
let function eat(){
console.log("吃吃吃");
}
const abc = {
name,
eat,
//方法的简写
run(){
comsole.log("别走好吗?跑起来");
}
}
6、箭头函数
箭头函数声明:
//普通方式声明函数:
let add = function(a,b){
return a+b;
}
//箭头函数声明:
let add = (a,b) => {
return a+b;
}
箭头函数特性
-
this时静态的,this始终指向函数声明时所在作用域下的this的值
function getName(){ console.log(this.name); } function getName1 = () => { console.log(this.name); } //设置window对象的name属性 window.name = "小王"; const school = { name: "小马" } //直接调用 getName();//小王 getName1();//小王 //call方法调用 getName.call(school);//小马 getName1.call(school);//小王
2.不能作为构造实例化对象
let Person = (name,age) => {
this.name = name;
this.age = age;
}
let me = new Person("小王",21);
comsole.log(me);//错误
3.不能使用arguments变量
let fn = () => {
console.log(arguments);
}
//调用函数
fn(1,3,6);//错误
4.箭头函数的简写:
-
省略小括号,当且仅当只有一个形参时。
let add = n => { return n+n; }
-
省略大括号,当函数体只有一条语句时,且return语句也要省略,语句的执行结果就是函数的返回值。
let pow = m => m*m;
箭头函数使用场景总结:
- 箭头函数适合与this无关的回调,定时器,数组的方法回调
- 箭头函数不适合与this有关的回调,事件回调,对象的方法
7、函数参数默认值
-
形参初始值
function add(a,b,c=3){ return a+b+c; } add(1,2);//输出1+2+3=6 //注意:具有默认值的参数,一般位置要靠后
2.与解构赋值结合
function getMsg({name,age}){
console.log(name);//小王
console.log(age);//21
};
getMsg({
name: "小王",
age: 21
})
//-------------------------------------
//也可以指定参数默认值
function getMsg({name="小马",age}){
console.log(name);//小马
console.log(age);21
};
getMsg({
age: 21
})
8、rest参数
es5引入rest参数,用来获取函数的实参,用来代替arguments
//ES5获取实参方式
function add(){
console.log(arguments);
}
add(1,4);
//ES6 rest获取实参方式
function pow(...args){
console.log(args);
}
pow("小王","小马","小丽");//返回一个数组,即可以使用filter some every map 等方法操作
注意:rest参数必须放到参数的最后面。
9、扩展运算符
...
扩展运算符能将数组转换为以逗号分割的参数序列。
//声明一个数组
const arr = ["小王","小马","小丽"];
function getName(){
console.log(arguments);
}
getName(arr);//["小王","小马","小丽"]
getName(...arr);//相当于getName("小王","小马","小丽");
扩展运算符的应用:
-
数组的合并
const arr1 = ["小王","小马"]; const arr2 = ["小瓦","小娥"]; //ES5数组合并 const result1 = arr1.concat(arr2); console.log(result1);//["小王","小马","小瓦","小娥"] //ES6 扩展运算符合并 const result2 = [...arr1,...arr2]; console.log(result2);//["小王","小马","小瓦","小娥"]
-
数组的克隆
const arr = ["A","B","C"]; const result = [...arr]; console.log(result);//["A","B","C"] //注意:如果arr中有引用类型,则为浅拷贝
-
将伪数组转换为真正的数组
//页面上有三个div <div></div> <div></div> <div></div> const arr = document.querySelectorAll('div'); const arrResult = [...arr]; console.log(arrResult);//[div,div,div]
10、Symbol
ES6引入了一种新的原始数据类型(Symbol),表示独一无二的值,是一种类似于字符串的数据类型。
Symbol的特点:
- Symbol的值时唯一的,用来解决命名冲突的问题。
- Symbol不能与其他数据类型进行运算,包括与自身类型计算。
- Symbol定义的队形属性不能使用for…in来循环遍历,可以用Reflect.ownKeys来获取对象的所有键名。
JS中的七种数据类型:
简写USONB :you are so niubility
U: undefined
S: String Symbol
O: Object
N: null number
B: boolean
Symbol的使用
-
给对象添加方法
let obj = {}; let methods = { up: Symbol(), down: Symbol() }; //给对象添加方法 obj[methods.up] = function(){ console.log("up"); } obj[methods.down] = function(){ console.log("down"); }
-
给对象添加属性
let obj = { name: "小王", //给对象添加属性 [Symbol("eat")]: function(){ console.log("eat"); } [Symbol("run")]: function(){ console.log("run"); } }
Symbol的内置值
11、迭代器(Iterator)
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口(对象的一个属性),就可以完成遍历操作。
原生具备Iterator接口的数据(可用for…of遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
工作原理:
a)创建一个指针对象,指向当前数据结构的起始位置。
b)第一次调用对象的next方法,指针自动指向数据结构的第一个成员。
c)接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员。
d)每调用next方法返回一个包含value和done属性的对象,done是一个布尔值,表示是否完成遍历。
示例:
const name = ["小王","小马","小丽"];
//使用for...of输出键值
for(let v of name){
console.log(v);
//输出小王 小马 小丽
}
//使用for...in输出键名
for(let v in name){
console.log(v);
//输出0 1 2
}
//原理
let iterator = arr[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());//小王 done:false
console.log(iterator.next());//小马 done:false
console.log(iterator.next());//小丽 done:false
console.log(iterator.next());//undefined done:true
迭代器的应用:
自定义遍历数据
//声明一个对象
const classs = {
name: "计科一班",
student: [
"小王",
"小马",
"小丽"
],
//添加iterator 由上面所描述的工作原理得
[Symbol.iterator](){
//记录索引
let index = 0;
let _this = this;
return {
next(){
if(index < _this.student.length){
const result = {value: _this.student[index],done: false};
//下标自增
index++;
//返回结果
return result;
}
else{
return {value: undefined,done: true};
}
}
};
}
}
//需求:使用for...of遍历classs中的student,每一次的结果返回student中的一个成员
for(let v of classs){
console.log(v);
//输出 小王 小马 小丽
}
12、生成器
生成器其实就是一个特殊的函数。
//声明一个生成器函数
function * gen(){
console.log("hello gen");
}
//调用函数
let g = gen();
console.log(g);//未输出hello gen
//解决方法,调用next方法
g.next();//输出hello gen
//yield是函数代码的分割符
function * gen(){
// console.log(1);
yield '第一部分';
// console.log(2);
yield '第二部分';
// console.log(3);
yield '第三部分';
// console.log(4);
};
let g = gen();
console.log(g.next());//{value: '第一部分',done: false}
console.log(g.next());//{value: '第二部分',done: false}
console.log(g.next());//{value: '第三部分',done: false}
console.log(g.next());//{value: undefined,done: true}
//for...of 遍历
for(let v of gen()){
console.log(v);
//输出1 2 3 4
}
生成器函数的参数传递
function * gen(arg){
console.log(arg);//AAA
let one = yield '第一部分';
console.log(one);//hello
};
//执行获取迭代器对象
let iterator = gen ("AAA");
console.log(iterator.next());
//next也可以传入实参,作为上一个yield语句的返回值
console.log(iterator.next("hello"));
生成器函数实例1:
//异步编程 文件操作 网络请求 数据库操作
//需求:1s后控制台输出111 2s后输出222 3s后输出333
//普通方法实现:
setTimeout(()=>{
console.log(111);
setTimeout(()=>{
console.log(222);
setTimeout(()=>{
console.log(333);
},3000);
},2000);
},1000);
//生成器函数实现:
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000);
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},2000);
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},3000);
}
//声明生成器函数
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
生成器函数实例2:
//需求:模拟获取数据(有先后顺序) 用户数据 订单数据 商品数据
function user(){
setTimeout(()=>{
let data = "用户数据";
//将用户数据作为参数传入
iterator.next(data);
},1000)
}
function order(){
setTimeout(()=>{
let data = "订单数据";
//将订单数据作为参数传入
iterator.next(data);
},1000)
}
function goods(){
setTimeout(()=>{
let data = "用户数据";
//将商品数据作为参数传入
iterator.next(data);
},1000)
}
//声明生成器函数
function * gen(){
let user = yield user();
console.log(user);//用户数据
let order = yield order();
console.log(order);//订单数据
let goods = yield goods();
console.log(goods);//商品数据
}
//调用生成器函数
let iterator = gen();
iterator.next();
13、Promise
Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取成功或者失败的结果。
//实例化Promise对象
const p = new Promise(function(resolve,reject){
//放异步操作的代码
setTimeout(()=>{
let data1 = "成功数据";
//let data2 = "失败数据";
resolve(data1);//执行成功,调用此函数
// reject(data2);//执行失败,调用此函数
},1000);
});
//调用Promise对象的then方法
p.then(function(value){
//当Promise对象执行成功,回调此函数
console.log(value);
},
function(reason){
//当Promise对象执行失败,回调此函数
console.log(reason);
});
封装 Promise读取文件实例:
//引入fs模块
const fs = require('fs');
//普通方法:
//调用方法读取文件
fs.readFile("C:/test.txt",(err,data)=>{//err为读取错误的信息,data为读取的内容
//如果读取失败,抛出异常
if(err) throw err;
//如果成功,输出读取的内容
console.log(data.toString());
});
//封装Promise读取文件
const p = new Promise(function(resolve,reject){
fs.readFile("C:/test.txt",(err,data)=>{
if(err) reject(err);
resolve(data);
});
});
//调用Promise的then方法
p.then(function(value){
console.log(value.toString());
},function(reason){
console.log("读取失败");
});
Promise封装ajax请求实例:
//普通方式处理网络请求
//1,创建对象
const xhr = new XMLHttpRequest();
//2、初始化
xhr.open("GET","https://xiaownagzi.club/network/test.json");//第一个参数为请求方式,第二个参数为请求地址
//3、发送
xhr.send();
//4、绑定事件,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态码200-299表示成功
if(xhr.status >= 200 && xhr.status <=299){
//成功输出响应结果
console.log(xhr.response);
}
else{
//失败输出状态码
console.error(xhr.status);
}
}
};
//Promise封装
const p = new Promise(function(resolve,reject){
//1,创建对象
const xhr = new XMLHttpRequest();
//2、初始化
xhr.open("GET","https://xiaownagzi.club/network/test.json");//第一个参数为请求方式,第二个参数为请求地址
//3、发送
xhr.send();
//4、绑定事件,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态码200-299表示成功
if(xhr.status >= 200 && xhr.status <=299){
//成功把响应结果回调出去
resolve(xhr.response);
}
else{
//失败把状态码回调出去
reject(xhr.status);
}
}
};
});
//处理请求响应的结果
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
});
Promise对象的then返回值问题:
//实例化Promise对象
const p = new Promise(function(resolve,reject){
//放异步操作的代码
resolve("hello");
});
//调用Promise对象的then方法
const result = p.then(function(value){
console.log(value);
//1、返回非Promise类型的数据
return 123;
//2、返回Promise类型
return new Promise((resolve,reject)=>{
resolve("成功");
});
//3、抛出异常
throw "error";
},
function(reason){
});
//输出then的返回值
console.log(result);
//输出结果分析:
//1、当then方法中没有返回值,则then返回的值时undefined,状态由Promise对象中的resolve,reject决定
//2、当then方法中有返回值,但返回值为非Promise类型的数据,状态为成功,返回的值为then方法中返回的值
//3、当then方法中返回Promise类型,then的返回的值是then方法中返回的值,状态为then方法中返回的状态
//4、抛出异常,状态为失败,then返回的值是then方法中抛出的的值
14、Set
ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值是唯一的,集合实现了Iterator接口,所以可以用扩展运算符和for…of
进行遍历。
//声明set
let s = new Set();
let s1 = new Set(["A","B","C","A"]);
console.log(s1);//A B C;set元素是唯一的,会自动去重
//set的方法
//1、获取元素的个数
s1.size();
//2、添加元素
s1.add("D");
//3、删除元素
s1.delete("A");
//4、查找元素
s1.has("B");
//5、清空元素
s1.clear();
//6、遍历set
for(let v of s1){
console.log(v);//A B C
}
Set的应用:
let arr1 = [1,2,3,4,5,4,3,2,1];
let arr2 = [4,5,6,5,6];
//1、数组去重
let result = [...new Set(arr1)];
console.log(result);//[1,2,3,4,5]
//2、求交集
let result = [...new Set(arr1)].filter(item=>{
let s2 = new Set(arr2);
if(s2.has(item)){
return true;
}
else{
return false;
}
});
console.log(result);//[4,5]
//3、求并集
let result = [...new Set([...arr1,...arr2])];
console.log(result);//[1,2,3,4,5,6]
//4、求差集
let result = [...new Set(arr1)].filter(item=> !(new Set(arr2).has(item)));
console.log(result);//[1,2,3]
15、Map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。Map也实现了Iterator接口,所以可以用扩展运算符和for…of遍历。
let m = new Map();
//添加元素
m.set("name","小王");//键为字符串
console.log(m);
m.set(["A","B"],"小王");//键为数组
console.log(m);
m.set({name: "小马"},"小王");//键为对象
console.log(m);
m.set(item=>{return item},"小王");//键为函数
console.log(m);
//结果如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-USUrGtGF-1622083120979)(C:\Users\Administrator\Desktop\map.png)]
//获取元素的个数
m.size();
//删除元素
m.delete("name");//参数为键名
//根据键名查找
m.get("name");
//清空
m.clear();
//遍历
for(let v of m){
console.log(v);
//输出结果为数组,起一个元素为键名,第二个元素为键值
}
16、class
//ES5定义类
function Person(name,age){
this.name = name;
this.age = age;
}
//添加原型方法
Person.prototype.run = function (){
console.log("我可以跑!!!");
}
//实例化
let mike = new Person("mike",22);
console.log(mike);
//调用方法
mike.run();
//ES6定义类
class Phone{
constructor(name,price) {
this.name = name;
this.price = price;
}
call(){
console.log("我可以打电话!!!");
}
}
//实例化
let Huawei = new Phone("华为",4999);
console.log(Huawei);
//调用方法
Huawei.call();
静态成员:
// ES5定义静态成员
function Person(){
}
Person.name = "小王";
Person.run = function (){
console.log("我可以跑!!!");
}
let mike = new Person();
console.log(mike.name);//报错
mike.run();//报错
// 结论:静态成员属于类不属于实例对象
//解决方法:
Person.prototype.name = "小jb王";
Person.prototype.run = function (){
console.log("我可以跑!!!");
}
//实例化
let mike = new Person();
console.log(mike.name);//成功
mike.run();//成功
//ES6定义静态成员
class Person{
static name = "小王";
static run(){
console.log("我可以跑");
}
}
//实例化
let mike = new Person();
console.log(mike.name);//报错
mike.run();//报错
//结论:静态成员属于类不属于实例对象
//解决方法:
console.log(Person.name);
Person.run();
ES5构造函数实现继承:
//ES5构造函数实现继承
//声明父类
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.run = function (){
console.log("我可以跑");
}
//声明子类
function HPerson(name,age,height){
Person.call(this,name,age);
this.height = height;
}
//设置子类构造函数的原型
HPerson.prototype = new Person();
//添加方法
HPerson.prototype.eat = function (){
console.log("我可以吃饭");
}
//实例化
let mike = new HPerson("mike",22,188);
mike.eat();//调用自己的方法
mike.run();//调用父类的方法
ES6实现继承:
//ES6实现继承
//声明父类
class Person{
constructor(name,age) {
this.name = name;
this.age = age;
}
run(){
console.log("我可以跑!!!");
}
}
//声明子类
class HPerson extends Person{
constructor(name,age,height) {
super(name,age);//相当于Person.call(this,name,age);
this.height = height;
}
//成员方法
eat(){
console.log("我可以吃饭!!!");
}
// 重写父类的方法
/* run(){
console.log("我可以很卖力的跑!!!!");
}*/
}
//实例化
let mike = new HPerson("mike",22,188);
mike.eat();//调用自己的方法
mike.run();//调用父类的方法
ype.run = function (){
console.log(“我可以跑”);
}
//声明子类
function HPerson(name,age,height){
Person.call(this,name,age);
this.height = height;
}
//设置子类构造函数的原型
HPerson.prototype = new Person();
//添加方法
HPerson.prototype.eat = function (){
console.log(“我可以吃饭”);
}
//实例化
let mike = new HPerson(“mike”,22,188);
mike.eat();//调用自己的方法
mike.run();//调用父类的方法
ES6实现继承:
```js
//ES6实现继承
//声明父类
class Person{
constructor(name,age) {
this.name = name;
this.age = age;
}
run(){
console.log("我可以跑!!!");
}
}
//声明子类
class HPerson extends Person{
constructor(name,age,height) {
super(name,age);//相当于Person.call(this,name,age);
this.height = height;
}
//成员方法
eat(){
console.log("我可以吃饭!!!");
}
// 重写父类的方法
/* run(){
console.log("我可以很卖力的跑!!!!");
}*/
}
//实例化
let mike = new HPerson("mike",22,188);
mike.eat();//调用自己的方法
mike.run();//调用父类的方法