ES6整理笔记

一、ES6简介

1、ECMAScript与JavaScript的关系

ECMAScript是JavaScript的规则,JavaScript是ECMAScript的一种实现。

2、ES6好处以及优势
  • let、const变量的声明(默认参数)
  • 变量的解构赋值
  • 字符串模板(多行字符串)
  • 箭头函数
  • Promise对象
  • Class类的概念
  • Module模块化
3、ES6与ES5的关系

ES6是ES5的语法糖

4、 ES6与ES7的关系

与ES6相比,ES7增加了关键词async的功能,并且可以使用await轻松直接调用函数来实现异步调用同步化。

二、ES5回顾

1、 严格模式
1)严格模式的原因
  • 消除JavaScript语法上的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全处、保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为新版本JavaScript做好铺垫;
2)关键词:‘use strict’
3)严格模式的特例
  1. 变量使用前必须要声明
var age=12;
console.log(age);
  1. 不能直接使用this指向
function f(name,age) {
this.name=name;
this.age=age;
return {a:this.name};
}
console.log(f("cn",20));
  1. eval函数存在作用域
var a="cn";
eval('var a="cn";console.log(a)');//cn1
console.log(a);//cn
2、JSON
1)JSON.parse()方法:将类似数组或对象格式的字符串转化为JSON格式的对象
var a="[1,2,3,4,5,6,7]";
console.log(typeof a);
console.log(typeof JSON.parse(a));
2)JSON.stringify()方法:将对象或数组转化为字符串
var b=[1,2,3,4,5];
console.log(typeof JSON.stringify(b));
3)实现数组或对象的深拷贝:JSON.parse(JSON.stringify(obj))
3、Object扩展
1)Object.create(原对象,[属性])

创建一个新的对象,原对象不会改变

var obj1={name:"cn",age:20};
var obj2=Object.create(obj1,{
	sex:{
		value:"女",//设置新增属性的值
		enumerable:true,//设置新增属性是否可以枚举显示,默认值是false(不会在输出对象引用中显示)
		writable:true,//设置新增属性是否可以修改,默认值是false
		configurable:true//设置新增属性是否可以删除,默认值是false
	},
	sex2:{
		value:"男",
		enumerable:true,
	}
})
console.log(obj1);//{name:"cn",age:20}
obj2.sex = "女孩"delete obj2.sex;//删除属性
console.log(obj2);
2)Object.defineProperties(原对象,扩展属性)

为指定对象定义扩展多个属性,会改变原对象的值

var obj1={name:"cn",age:20};
var obj2=Object.defineProperties(obj1,{
	sex:{
		get() {//获取该属性值的时候被调用
			console.log("我是get方法");
			return "女";
		},
		set(v) {//设置该属性值的时候被调用
			console.log("我是set方法"+v);
		}
	}
});
obj2.name="cn1";
obj2.sex="男";
console.log(obj1);
console.log(obj2.sex);
4、Array扩展
1)引用名.forEach()

没有生成值或返回值,只可以循环遍历数组。

let arr=[1,2,3,4,5];
var arr1=arr.forEach(function (item ,index) {
return index;
});
console.log(arr1);//undefined
2)引用名.map()

可以根据返回值进行生成新的数组(即返回值组成的数组),也可以循环遍历数组

var arr2=arr.map(function (item,index) {
return index>3;
})
console.log(arr2);//数组
3)引用名.filter()

可根据返回值判断:返回值为true,则会将对应的数组的值返回并生成新的数组。
功能;过滤数组。

var arr3=arr.filter(function (item ,index) {
//return index>2;
return true;//只是用来判断当前值,是否添加到新的数组中。
});
console.log(arr3);
5、函数扩展
1)函数名.bind(obj)

将函数内部的this绑定为obj,并将函数返回

function f(name,age) {
this.name=name;//cn
this.age=age;//20
console.log(this.name);
return {name:this.name,age:this.age};
}
var obj={};
//bind方法将自定义对象和this进行绑定
f.bind(obj)("cn",20);
console.log(f.bind(obj));
6、let和const
1) 语句块

{语句块}
for(){语句块}
if(){语句块}
function a(){语句块}

2)顶层对象

在浏览器环境下,顶层对象是window和_self;在Node中,顶层对象是global。ES2020在标准语言的层面,引入globalThis作为顶层对象,在任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指全局下的this。

3) let

定义变量

4) const

定义常量,声明的同时需要初始化。当数据类型为Number、Boolean、String时,值不可改变;但是对对象或数组时,值可以改变,因为声明的变量相当于指向内存的地址。
注:将对象冻结:Object.freeze()

5) let和const特性
  • 块级作用域
  • 不存在变量提升,暂时性死区(TZD)
  • 同一作用域,不能重复声明变量
6)let和var的区别
  1. 作用域不同,let是块作用域,var是函数作用域;
  2. let在同一作用域不能重复声明,var可以覆盖同名变量;属于TDZ问题
  3. let不存在变量声明提升,var存在;要遵守先声明后使用的原则
7、变量的解构赋值和默认值
1)解构

概念:ES6允许按照一定的模式(即规则),从数组和对象中提取,对变量进行赋值。

解构赋值肯定有赋值运算符,赋值运算符左边的 {} 或 []是模式,右边的是对象或数组。

对象的大括号不是作用域

2)数组的解构赋值
let [foo,[[bar],c]] = [1,[[2],3]];//1 2 3
let [,,third]=["foo","bar","baz"];//baz
let [x,,y]=[1,2,3];//1 3
let [head,...tail]=[1,2,3,4];//1 [2,3,4]
let [x,y,...z]=["a"];//a undefined []
let [bar,foo]=[1];//1 undefined
let [x,y]=[1,2,3];//1,2
let [a,[b],d]=[1,[2,3],4];//1 2 4
let [x,y,z]=new Set(['a','b','c']);//a b c
let [foo=true]=[];//true
let [x,y='b']=['a'];//a b
let [x,y='b']=['a',undefined];//a b
let [x=1]=[null];//null
let [x=1,y=x]=[];//1 1
let [x=1,y=x]=[2];//2 2
let [x=1,y=x]=[1,2];//1 2
let [x=y,y=1]=[];//报错
function f() {
console.log("aaaa");
return "bbb";
}
let [x=f()]=["sdfsdfsdf"];//惰性解构赋值
console.log(x);//sdfsdfsdf
3)对象的解构赋值

对象的属性没有次序,变量必须与属性同名才能取到正确的值。

let {log,sin,cos}=Math;//[Function: log] [Function: sin] [Function: cos]

let {foo:a,foo1:b}={foo:"aaa",foo1:"bbb"};
console.log(a,b);//aaa bbb

let obj={};
let arr=[];
({a:obj.prop,b:arr[0] }={a:"asdasdasd",b:true })//将解构赋值的对象放到()中,可以抵消{}的代码块作用
console.log(obj);//{ prop: 'asdasdasd' }
console.log(arr);//[ true ]

let {log}=console;
log("aaaaaaa");//这两行代码相当于console.log();

let {x = 3} = {};//3
let {x, y = 5} = {x: 1};//1 5
let {x: y = 3} = {};//报错x is not defined 3
let {x: y = 3} = {x: 5};//报错 5
let {x = 3} = {x: undefined}; //3
let {x = 3} = {x: null};//null
({} = [true, false]);
({} = 'abc');
({} = []);

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;//1 3

let x;
//{x} = {x: 1};
({x} = {x: 1});//1
4)解构赋值的作用
  1. 交换值
let a = 1;
let b = 2;
let c = 3;
[a,b,c] = [b,c,a];
console.log(a,b,c);//2 3 1
  1. 从对象或数组中解构所需要的值
let obj = {
a:{
b:"bbb",
c:"ccc",
d:{
e:"eee"
}
}
};
let {a:{d:{e}},a:{d}}=obj;
console.log(e);//eee
console.log(d);//{ e: 'eee' }
//如果要解构最深层,它的上一级一定要有
console.log(c);//报错,未解构的变量是无法打印的
//解构的时候是一一对应的
  1. 从函数的返回值中解构所需要的值
function f(){
return [1,2,3,4];
}
let [,a,,,b]=f();
console.log(a,b);//2 undefined
  1. 函数参数的解构(支持不完全解构)
function f([a,b,c,d]){
return a+c;
}
console.log(f([1,,7,]));//8
  1. 可以解构map数据结构类型的key-value
let map = new Map();
map.set("a","aaa");
map.set("b","bbb");
// console.log(map);
for(let [index,value] of map){
// console.log(value);
console.log(index)
}
  1. 从指定的模块中解构对应的方法
const {readFile}=require("fs");

三、模板字符串

`字符内容${变量输出}字符内容`

:${ }中的值:

  1. 变量
  2. 任意javascript表达式
  3. 获取对象的属性
  4. 调用函数

四、对象的扩展

1、对象的简写
1)对象属性名的简写
let a="aaa";
let b={a};
console.log(b);//{ a: 'aaa' }、

function f() {
let name="cn";
let age=20;
let sex="女";
return {name,age,sex};//相当于{name:name,age:age,sex:sex}
}
console.log(f());//{ name: 'cn', age: 20, sex: '女' }
2)对象方法名的简写
let a={
f(){
console.log("aaa");
},
f1(){
console.log("aaaaa2");
}
}
//调用
a.f1();//aaaaa2


let aa="haha";
let obj={
a:"saddfsa"
};
let obj2={
[aa]:"sadsfd"
}
console.log(obj2);//{ haha: 'sadsfd' }
console.log(obj2[aa]);//sadsfd
console.log(obj2.haha);//sadsfd


function f(aname) {
return{
[aname]:"cn"
}
}
console.log(f("a").a)//cn

function f(fnname) {
return{
[fnname](){
console.log("我是函数,缺省名字的函数")
}
}
}
console.log(f("aa"));//{ aa: [Function: aa] }
console.log(f("aa").aa);//[Function: aa]
f("aa").aa();//我是函数,缺省名字的函数
2、对象中变量
1)变量做属性名
let name = 'cn';
const a = {
'age':20,
[name]:'cc'//name是一个变量
};
console.log(a['age']);//20
console.log(a[name]);//cc
console.log(a['cn']);//cc
2)变量做方法名
let obj={
['na'+'me'](){
return 'cn';
}
};
obj.name();

五、箭头函数

1、语法

()=>{}

2、参数
1)无参数
let f=()=>{
cnsole.log('a');
}
1)一个参数

可将()省略

let f=n=>{
consle.log('a');
}
1)两个及以上参数
var fu = (n,m=10)=>{
return n*m;
}
3、返回值
1)函数体内是一条语句

{}可省略

let f=n=>console.log(n);
2)函数体内是一条语句,并且是return关键词

省略{}和return

let f=(n,m)=>n*m;
4、使用场景

箭头函数的两个不适用场景:

  1. 对象里面
  2. 事件的回调函数
button.on('click',function(e){
console.log(this)
})
1)回调函数中的箭头函数
let timer=setTimeout(()=>{
console.log(1);
},1000);
2)参数中的箭头函数
function fn(f,a){
console.log(a);
}
fn(()=>{
console.log('我是参数箭头函数');
},10);
5、箭头函数中this的使用规则

箭头函数的this不绑定当前调用者,只与箭头函数定义的上下文环境有关。

1)全局函数中的this
function fun(){
console.log(this);//window 
}
let fun1 = n =>{
console.log(this); //window 
}
2)事件处理函数中的this
let oDiv = document.getElementById("box"); 
oDiv.onclick = function () {
console.log(this);//div
}
oDiv.onclick = ()=>{
console.log(this); //window 
}
3)对象方法中的this
function Person() {
this.eat = function () {
return function () { 
console.log(this); //global
}
}
}
let p = new Person(); 
p.eat()();

function Dog() {
this.eat = function () {
return ()=>{ 
console.log(this); //Dog
} 
}
}
let d = new Dog(); d.eat()();
6、箭头函数的特性
  1. 箭头函数是匿名函数,不绑定自己的this,arguments,super,new.target
  2. 箭头函数会捕获其所在上下文的this值,作为自己的this值,在使用call/apply绑定时,会改变this指向。
  3. 箭头函数不绑定arguments,取而代之用rest参数运算符解决
  4. 箭头函数不能作为构造函数,和 new 一起用就会抛出错误

六、ES6中的运算符

1、rest剩余参数运算符

将以“,”隔开的参数转换为数组
注:剩余参数运算符一定要在形参的最后

function f(b,c,...a) {
console.log(a,b,c);//[3, 4, 5, 6, 7, 8, 9, 10, 11] 1 2
}
f(1,2,3,4,5,6,7,8,9,10,11);
2、spread扩展运算符

将一个数组转为用逗号隔开的参数,通常使用在实参的传递中

用于:给函数传参的时候,不确定传参的个数,并且还要调用的时候

function f(a,b,c,d,e) {
console.log(a,b,c,d,e);// 1 2 3 undefined undefined
}
let arr=[1,2,3];
f(...arr);
1)spread 扩展运算符的应用场景:
  1. 复制、合并数组或对象
    (一维数组:深拷贝;多维数组:浅拷贝)
//复制数组
let arr=[1,2,3];
let arr2=[...arr];//深拷贝(值)
console.log(arr2);//[ 1, 2, 3]

//合并数组
let arr=[1,2,3];
let arr2=[4,5,6];
let newArr=[...arr,...arr2];//合并拷贝,深拷贝(值)
console.log(newArr);//[ 1, 2, 3, 4, 5, 6 ]
  1. 将类似数组或对象转为真正的数组。
let set=new Set();
set.add("aaaa");
set.add("bbbb");
console.log([...set]);//[ 1, 2, 3, 4, 5, 6 ]

七、Symbol

ES第7种数据类型(基本数据类型)

1、定义Symbol类型变量,无参形式

即使使用了参数,参数相当于描述

let a=Symbol();
let b=Symbol();
console.log(a===b);//false
2、Symbol的使用
let a=Symbol();
let obj={
//变量名做属性名
[a]:"hahaha"
}
obj[a]="aaaaaaa";//修改
console.log(obj[a]);//aaaaaaa

let a=Symbol();//生成唯一的哈希值
let b=Symbol();//生成唯一的哈希值
let obj={
[a]:"hahaha"
}
obj[b]="aaaaaaa";
console.log(obj);//两个 { [Symbol()]: 'hahaha', [Symbol()]: 'aaaaaaa' }
3、模拟实现私有属性
function Person() {
let a=Symbol();
let b="bl";
this[a]=()=>{
console.log("我是私有属性");
}
this[b]=()=>{
// this[a]();
console.log("我是单独的方法");
return a;
}
}
const p=new Person();
// console.log(p);//Person { bl: [Function], [Symbol()]: [Function] }
p[p.bl()]();
p.bl();
4、Symbol的for方法可以将两个Symbol定义成同一个Hash
let a=Symbol.for("aaa");
let b=Symbol.for("aaa");
console.log(a===b);//true
console.log(typeof a);//symbol
3、ES6中的Symbol类型有什么作用?

ES6新增了Symbol数据类型,它用来生成一个独一无二的值,Symbol数据常用来给对象属性赋值,让对象属性具备唯一性,不容易被覆盖。

八、Set和Map数据结构

1、Set数据结构

类似数组,与数组的区别在于其内部成员是唯一的(即没有重复元素)。

Set数据结构本身可以去重(数字类型,布尔类型,字符类型)

:同一变量名声明的数组可能去重,在未重新赋值的情况下可以去重,只要重新赋值了即使与原来的值相同也不能去重;不同变量存储的数组不会去重(因为存的是地址)

1)语法
let set = new Set(数组);//注:参数可以省略
2)常用属性
  1. size:获取set结构内元素的数量。
3)常用方法
  1. add(value):添加某个值,返回 Set 结构本身。
  2. delete(value):删除某个值,返回一个布尔值,表示删除是否成功,如果元素不存在代码不会报错可以正常执行
  3. has(value):返回一个布尔值,表示该值是否为Set的成员。
  4. clear():清除所有成员,没有返回值。
  5. forEach:遍历Set结构内的元素。
4)Set用来过滤数组重复数据:let arr = […new Set(arr)];
2、Map数据结构

类似对象,区别在于对象只接受字符串作为键名,而
Map的键名可以是任意类型。

1)语法
let set = new Map(初始化的值);//注:参数可以省略
2)常用属性
  1. size:获取Map结构内元素的数量。
3)常用方法
  1. set(key,value):添加一个键值数据。
  2. get(key):根据key获取value。
  3. has(key):返回一个布尔值,表示map集合是否包含当前key的成员。
  4. delete(key):根据指定的key删除数据。
  5. clear():清除所有成员,没有返回值。
  6. forEach:遍历Map集合使用forEach。

九、Iterator遍历器

1、ES6中的四种数据结构:

数组(Array)、对象(Object)、Map、Set

2、概念

Iterator是一种接口,所以的数据结构只要部署了接口,都可以进行遍历。

作用:循环遍历输出

Symbol.iterator是属性,本身也是封装好的函数,让定义好的数据结构可以遍历

3、ES6中天生可以遍历的:

Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象

4、遍历
let arr=["a","b","c","d","e"];
let it=arr[Symbol.iterator]();//将遍历器属性绑定到自定义的数据结构中,这里定义的变量it相当于一个指针
it.next();//{value:"a",done:false}
it.next();//{value:"a",done:false}
console.log(it.next());//{value:"a",done:false}
//第六次调用it.next()输出 {value:undefined,done:true}

for(let item of it){
console.log(item);//d e
// console.log(item.next());//报错 如果使用for...of遍历遍历器指针,则不能再使用next()方法
}

十、Generator函数

是ES6提供的一种异步编程解决方案,封装了多个内部的状态;

1、Generator函数的定义

定义的关键词:*(用来修饰函数名) 、yield(用来定义状态)

function *f() {
yield "我是状态一";
yield "我是状态二";
yield "我是状态三";
return "我是G函数返回值";
}
2、Generator函数的调用
1)无参
let git=f();
//获取Genertor函数中的状态
//console.log(git.next());//{ value: '我是状态一', done: false }
//console.log(git.next());//{ value: '我是状态二', done: false }

//注:采用for...of循环只能输出generator函数的状态,无法拿到return的返回值
for (let item of git){//Generator函数默认实现了遍历器接口Symbol.iterator
console.log(item);//我是状态一 我是状态二 我是状态三
}

git.next();
git.next();
console.log(git.next());
console.log(git.next());//{ value: '我是G函数返回值', done: true } 拿到return的返回值
console.log(git.next());//此时{value:undefined,done:true} 再继续git.next()都是这个值
2)可以接受参数的next()方法
function * f1() {
let a=yield "我是状态一";
console.log("我是yield一的输出"+a);
let b=yield "我是状态二";//yield "我是状态二";let a="我是next传参二";
console.log("我是yield二的输出"+b);
yield "我是状态三";
return "我是G函数返回值"
}
let gitf1=f1();
//yield关键词本身具备懒惰原理,
//next参数会赋值给上一个状态,使用next()方法传参,yield的懒惰性,会将参数赋值给上一个状态,即是上一个状态的值
console.log(gitf1.next("我是next传参一"));
console.log(gitf1.next("我是next传参二"));
console.log(gitf1.next("我是next传参三"));
3、Generator函数用同步思想解决异步
function * f() {
let a=yield getData();
console.log(a);
}
let fnn=f();
function getData() {
$.get("./user.json").then((data)=>{
//console.log(data);
//f().next(data);//这样写默认看成了f()这个方法的调用
fnn.next(data);
})
}
fnn.next();

十一、Promise对象

Promise和callback一样,目的都是为了异步数据传递,比如ajax请求数据的传递

1、概念

异步编程的一种解决方案,也称之为一个容器,黑箱操作;

2、特点:
  1. 对象的状态不受外界影响;

  2. 一旦状态改变,就不会再变; 状态不可逆 不能互相转换

3、状态:

pending(进行中)、fulfilled(成功)对应的方法resolve()、rejected(失败)对应的方法reject()

4、缺点:
  1. 无法取消Promise;

  2. 不设置回调函数,内部抛出的错误不会反应到外部

  3. pending状态,无法确定进度;

5、对象的实例方法

Promise对象的结果有两个方法:resolve()–已成功(fulfilled) reject()–已失败(rejected)

//1、resolve()
//2、reject()
//例一
function f(){
return new Promise((resolve,reject)=>{
setTimeout(resolve,3000,"我是字符串");//setTimeout的第三个参数是用来给第一个参数赋值的
})
}

//3、then()获取成功状态的值
f().then((data)=>{
console.log(data);//3s后 输出 我是字符串
})
//console.log(f());//Promise { <pending> }

//例二:用伪代码来表示Promise对象的一个状态传值(实例)
function f() {
return new Promise((resolve,reject)=>{
if(1)
resolve("代码执行成功")
else
reject("代码执行失败")
})
}

//例三:
function f() {
return new Promise((resolve, reject) => {
reject("想用失败传值");
})
}
// Promise对象的then方法,参数一是成功的回调函数,参数二是失败的回调函数(通常不建议使用)
f().then((data)=>{
console.log(data);
},(error)=>{
console.log(error)
})

//例四
function f() {
return new Promise((resolve, reject) => {
resolve("想用成功传值");
reject("想用失败传值");
// console.log(a);
// let a = 2;
// throw关键词 抛出关键词 可以抛出自定义错误
// throw new Error("我是自定义的错误!")
})
}
f().then((data)=>{
console.log(data);
}).catch((err)=>{//4、catch()方法可以捕获错误、异常、失败的传值
console.log(err.message);
}).finally(()=>{//5、finally()方法,最终方法,不管Promise对象是成功状态,还是失败状态,还是出现错误,finally方法都会被执行
console.log("我是finally");
})

//6、all()方法
// 当all方法中全部都是成功状态的时候,会以数组的形式输出全部成功的结果;
// 当all方法中存在失败状态的时候,那么它会返回第一个失败的结果;


//7、race()方法:只会返回第一个Promise的状态,不论成功还是失败

十二、async函数

1、简介

async函数,本质就是Generator函数的语法糖;

语法:将Generator函数的*换成async(在function前),将yield换成await;

返回一个Promise对象,可以添加then()方法添加回调函数;

function f() {
return new Promise((resolve,reject)=>{
setTimeout(resolve,3000,"我我");
})
}
async function testAsync() {
let a=await f();//await可以将异步操作同步化。
console.log(a);
}
testAsync()

//async关键词可以独立出现,但是await关键词不能独立出现,如果需要使用await必须用async来修饰函数
async function testAsync2() {
await f();
console.log("aaaaa");
}
testAsync2();
2、async函数中的return关键词
//错误处理
//方法一:
async function f() {
let a=await Promise.resolve("成功执行");
console.log(a);
//当try块中出现错误或异常时,如果采用了catch块捕获,则只会影响try块内部的代码,不会影响其外部的代码
try {
let b=await Promise.reject("我是失败");
console.log(b);
}catch {
//console.log(e);
}finally {
console.log("我是永久执行块")
}
let c=await Promise.resolve("我是成功二");
console.log(c);
return "我是返回值";
}
f().then((data)=>{
console.log(data);
});

//方法二:
//除了采用try...catch进行捕获外,还可以采用Promise对象本身的catch方法,进行捕获。
async function f() {
let a=await Promise.resolve("成功执行");
console.log(a);

let b=await Promise.reject("我是失败").catch((err)=>{
console.log(err);
});
// console.log(b);

let c=await Promise.resolve("我是成功二");
console.log(c);
return "我是返回值";
}
f().then((data)=>{
console.log(data);
});

//方法三:
//优雅处理async。。。await的异常
function f(msg) {
return new Promise((resolve,reject)=>{
//resolve("sssss");
reject(`我是第${msg}次失败`);
})
}
function to(p) {
return p.then((data)=>{return [data,null]}).catch((err)=>{return [null,err]});
}
async function f1() {
//let [data,err]=await f(1)
let [data,err]=await to(f(1));
console.log(data);
console.log(err);
let [data1,err1]=await to(f(2))
console.log(data1);
console.log(err1);
}
f1();

十三、面向对象

1、面向对象编程

本质是以建立模型体现出来的抽象思维过程和面向对象的一些方法。模型是用来反映现实世界中事物理特征。方法是模型所需要的行为动作。

2、面向对象特点:

封装、继承、多态

十四、Class类

1、定义类

关键词class

class 类名 {}

2、类中的元素
1)类的构造方法

关键词:constructor

constructor()方法是类的默认方法,通过new生成对象实例时会自动调用该方法。

作用:1.给变量赋值;2.声明变量

2)成员函数/方法

在成员方法中声明的变量是不能在外面调用的(undefined)

3)成员变量(在类中定义成员变量,变量名直接赋值)

在类中声明成员变量有两种方法:

  1. 变量名=值
  2. this.变量名=值

注:

  • 如果是同一变量名,this可以执行赋值功能
  • 在类的作用域声明的变量,它绑定到类;在构造方法中声明的变量,它也是绑定到类;
  • 如果在方法中使用this绑定到类上的变量,需要调用方法后才能使用,否则不会绑定到类上
  • 如果在类的一个成员方法中使用另一个成员方法中的变量,一点要先调用声明的成员方法才能使用
  • 类中的一个成员方法需要调用另一个成员方法,采用关键词this.成员方法名
class Person {
name = "cn";//类的成员变量

// constructor() {//类的构造方法(是给变量赋值的,声明变量)
// this.name = "cn1";//this关键字代表实例的对象
// }
// 其他语言可以有多个构造方法,但ES6只能有一个构造方法
constructor(name) {
this.name = name;
}

addSmoking(){//类的成员方法
//在成员方法中声明的变量是不能在外面调用的(undefined)
let name1 = "aaa"
this.name2="bbb";

// 类中成员变量的使用需要使用关键词this,如this.name
console.log("我是"+this.name);
}

addSpeaking(){
// 在一个成员方法中调用另一个成员方法,采用关键词this.成员方法名
this.addSmoking();
console.log(this.name2);
}
}

// 类在使用的时候需要实例化
// 注:在给类实例化的时候,会默认调用构造方法,如果构造方法需要参数,需要在实例化的时候传递实参
// 如果没给变量赋值,默认就是undefined
let p = new Person("cn2");
p.addSmoking();

类中两种变量:成员变量、静态变量

三种方法:成员方法、静态方法、构造方法

3、static

调用静态变量:类名.变量名

调用静态方法:类名.方法名

构造方法中不能声明静态变量;
成员方法中,可以使用静态变量和静态方法,必须使用类名调用;
静态方法中,不能使用成员变量和成员方法,但可以使用静态变量和静态方法,调用方式可以是类名也可以是this

class Person {
static age=20;
name="cn";
constructor(){//构造方法
this.age="女";
}
addSmoking(){//成员方法
Person.addListen();
console.log(this.name,this.age);//this.age是undefined,必须要用类名来调用
}
ststic addListen(){//声明静态的方法
console.log("我是静态方法"+this.age);
}
}
let p=new Person();
p.addSmoking();
Person.addListen();//调用静态的方法
Person.age=12;//静态变量的赋值和调用
4、继承

ES6中的继承是完全继承

关键词:extends

存储机制:

内存块中存的是静态方法和静态属性(预加载时存储);成员方法和成员属性在运行时存储

1.子类中可以重新定义父类中的方法和属性,这种形式称之为多态
2.子类中如果需要使用父类的方法,可以采用super关键词调用对应的方法

3.子类不能在成员方法中使用super调用父类的静态方法,会产生运行时错误,可以使用类名里调用父类的静态方法;

4.子类中如果需要使用父类的静态属性,可以使用this
5.子类的构造方法中必须要调用父类的构造方法,语法:super()
6.类中的super关键词指向父类,类的this关键词指向当前类

class Father {
firstName="r";
static sex="男";
constructor() {
this.secondName="p";
}
addSmoking(){
console.log("我是父类中的s");
}
static addDrinking(){
console.log("我是父类中的d");
}
}
class Child extends Father{
firstName="y";
constructor() {
super();//调用父类的构造方法
}
addSmoking() {
//console.log(this.firstName)
//super.addSmoking();
//super.addDrinking();//不能再成员方法中使用super调用父类的静态方法,会产生运行时错误。但是可以使用类名来调用静态的方法
//console.log(this.firstName)
console.log(Father.sex)//可以使用类名来获取静态属性。
Father.addDrinking();
console.log("我是儿子的ns");
}
static addDrinking(){
console.log(this.sex)
super.addDrinking()
console.log("我是儿子的nd");
}
}
const c=new Child();
//c.addSmoking();
// // console.log(c.firstName)
Child.addDrinking();
// console.log(Child.sex)在这里插入代码片
5、属性的修饰符
class A {
username="cn";
//uname是属性名
set uname(value){//set修饰的属性名方法,当给属性名赋值的时候被调用
console.log("我是set修饰的方法")
this.username=++value;
}
get uname(){//get修饰的属性名方法,当输出属性的时候被调用
console.log("我是get修饰的方法")
return this.username;
}
}
// 类必须使用new调用,否则会报错。
const a=new A();
a.uname=123;//调用set修饰的属性名方法
console.log(a.uname);//调用get修饰的属性名方法

十五、数组的扩展

1、静态方法
(1)Array.from()

将对象转化为数组
注:

  1. 只能将key为下标的对象转为数组(支持隐式转换);
  2. 且对象中必须要有length属性,因为新生成的数组需要根据length值来生成元素的个数,
  3. 如果对应下标没有值,则会使用undefined填充;
  4. 如果出现重复下标则会覆盖值;
let obj={1:"aaa",2:"bbb",3:"ccc",length:7,3:"ss",5:"eee"};
console.log(Array.from(obj));
2)Array.of()

将值转化为数组

console.log(Array.of(1,2,3,4,5,"ssss"));
2、成员方法
1)引用.entries()

将数组以[index,value]新数组的形式返回

2)引用.keys()
3)引用.values()
4)引用.includes(值,searchIndex)

查询数组中是否含有参数一的值,返回值是布尔类型;

参数二是开始查找的下标(包含起始下标),负值:从最大长度开始往左数参数个

includes()方法可以实现模糊搜索,但是区分大小写

5)find()

也是查找,查找数组中满足回调函数中return条件的第一个元素

6)some()

搜索当前数组中是否含有满足回调函数返回值的值,如果有返回true,没有返回false

7)every()

搜索当前数组中的值必须全部都满足回调函数的返回值,满足返回true,否则返回false

一、ES6简介

1、ECMAScript与JavaScript的关系

ECMAScript是JavaScript的规则,JavaScript是ECMAScript的一种实现。

2、ES6好处以及优势
  • let、const变量的声明(默认参数)
  • 变量的解构赋值
  • 字符串模板(多行字符串)
  • 箭头函数
  • Promise对象
  • Class类的概念
  • Module模块化
3、ES6与ES5的关系

ES6是ES5的语法糖

4、 ES6与ES7的关系

与ES6相比,ES7增加了关键词async的功能,并且可以使用await轻松直接调用函数来实现异步调用同步化。

二、ES5回顾

1、 严格模式
1)严格模式的原因
  • 消除JavaScript语法上的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全处、保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为新版本JavaScript做好铺垫;
2)关键词:‘use strict’
3)严格模式的特例
  1. 变量使用前必须要声明
var age=12;
console.log(age);
  1. 不能直接使用this指向
function f(name,age) {
this.name=name;
this.age=age;
return {a:this.name};
}
console.log(f("cn",20));
  1. eval函数存在作用域
var a="cn";
eval('var a="cn";console.log(a)');//cn1
console.log(a);//cn
2、JSON
1)JSON.parse()方法:将类似数组或对象格式的字符串转化为JSON格式的对象
var a="[1,2,3,4,5,6,7]";
console.log(typeof a);
console.log(typeof JSON.parse(a));
2)JSON.stringify()方法:将对象或数组转化为字符串
var b=[1,2,3,4,5];
console.log(typeof JSON.stringify(b));
3)实现数组或对象的深拷贝:JSON.parse(JSON.stringify(obj))
3、Object扩展
1)Object.create(原对象,[属性])

创建一个新的对象,原对象不会改变

var obj1={name:"cn",age:20};
var obj2=Object.create(obj1,{
sex:{
value:"女",//设置新增属性的值
enumerable:true,//设置新增属性是否可以枚举显示,默认值是false(不会在输出对象引用中显示)
writable:true,//设置新增属性是否可以修改,默认值是false
configurable:true//设置新增属性是否可以删除,默认值是false
},
sex2:{
value:"男",
enumerable:true,
}
})
console.log(obj1);//{name:"cn",age:20}
obj2.sex = "女孩"delete obj2.sex;//删除属性
console.log(obj2);
2)Object.defineProperties(原对象,扩展属性)

为指定对象定义扩展多个属性,会改变原对象的值

var obj1={name:"cn",age:20};
var obj2=Object.defineProperties(obj1,{
sex:{
get() {//获取该属性值的时候被调用
console.log("我是get方法");
return "女";
},
set(v) {//设置该属性值的时候被调用
console.log("我是set方法"+v);
}
}
});
obj2.name="cn1";
obj2.sex="男";
console.log(obj1);
console.log(obj2.sex);
4、Array扩展
1)引用名.forEach()

没有生成值或返回值,只可以循环遍历数组。

let arr=[1,2,3,4,5];
var arr1=arr.forEach(function (item ,index) {
return index;
});
console.log(arr1);//undefined
2)引用名.map()

可以根据返回值进行生成新的数组(即返回值组成的数组),也可以循环遍历数组

var arr2=arr.map(function (item,index) {
return index>3;
})
console.log(arr2);//数组
3)引用名.filter()

可根据返回值判断:返回值为true,则会将对应的数组的值返回并生成新的数组。
功能;过滤数组。

var arr3=arr.filter(function (item ,index) {
//return index>2;
return true;//只是用来判断当前值,是否添加到新的数组中。
});
console.log(arr3);
5、函数扩展
1)函数名.bind(obj)

将函数内部的this绑定为obj,并将函数返回

function f(name,age) {
this.name=name;//cn
this.age=age;//20
console.log(this.name);
return {name:this.name,age:this.age};
}
var obj={};
//bind方法将自定义对象和this进行绑定
f.bind(obj)("cn",20);
console.log(f.bind(obj));
6、let和const
1) 语句块

{语句块}
for(){语句块}
if(){语句块}
function a(){语句块}

2)顶层对象

在浏览器环境下,顶层对象是window和_self;在Node中,顶层对象是global。ES2020在标准语言的层面,引入globalThis作为顶层对象,在任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指全局下的this。

3) let

定义变量

4) const

定义常量,声明的同时需要初始化。当数据类型为Number、Boolean、String时,值不可改变;但是对对象或数组时,值可以改变,因为声明的变量相当于指向内存的地址。
注:将对象冻结:Object.freeze()

5) let和const特性
  • 块级作用域
  • 不存在变量提升,暂时性死区(TZD)
  • 同一作用域,不能重复声明变量
6)let和var的区别
  1. 作用域不同,let是块作用域,var是函数作用域;
  2. let在同一作用域不能重复声明,var可以覆盖同名变量;属于TDZ问题
  3. let不存在变量声明提升,var存在;要遵守先声明后使用的原则
7、变量的解构赋值和默认值
1)解构

概念:ES6允许按照一定的模式(即规则),从数组和对象中提取,对变量进行赋值。

解构赋值肯定有赋值运算符,赋值运算符左边的 {} 或 []是模式,右边的是对象或数组。

对象的大括号不是作用域

2)数组的解构赋值
let [foo,[[bar],c]] = [1,[[2],3]];//1 2 3
let [,,third]=["foo","bar","baz"];//baz
let [x,,y]=[1,2,3];//1 3
let [head,...tail]=[1,2,3,4];//1 [2,3,4]
let [x,y,...z]=["a"];//a undefined []
let [bar,foo]=[1];//1 undefined
let [x,y]=[1,2,3];//1,2
let [a,[b],d]=[1,[2,3],4];//1 2 4
let [x,y,z]=new Set(['a','b','c']);//a b c
let [foo=true]=[];//true
let [x,y='b']=['a'];//a b
let [x,y='b']=['a',undefined];//a b
let [x=1]=[null];//null
let [x=1,y=x]=[];//1 1
let [x=1,y=x]=[2];//2 2
let [x=1,y=x]=[1,2];//1 2
let [x=y,y=1]=[];//报错
function f() {
console.log("aaaa");
return "bbb";
}
let [x=f()]=["sdfsdfsdf"];//惰性解构赋值
console.log(x);//sdfsdfsdf
3)对象的解构赋值

对象的属性没有次序,变量必须与属性同名才能取到正确的值。

let {log,sin,cos}=Math;//[Function: log] [Function: sin] [Function: cos]

let {foo:a,foo1:b}={foo:"aaa",foo1:"bbb"};
console.log(a,b);//aaa bbb

let obj={};
let arr=[];
({a:obj.prop,b:arr[0] }={a:"asdasdasd",b:true })//将解构赋值的对象放到()中,可以抵消{}的代码块作用
console.log(obj);//{ prop: 'asdasdasd' }
console.log(arr);//[ true ]

let {log}=console;
log("aaaaaaa");//这两行代码相当于console.log();

let {x = 3} = {};//3
let {x, y = 5} = {x: 1};//1 5
let {x: y = 3} = {};//报错x is not defined 3
let {x: y = 3} = {x: 5};//报错 5
let {x = 3} = {x: undefined}; //3
let {x = 3} = {x: null};//null
({} = [true, false]);
({} = 'abc');
({} = []);

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;//1 3

let x;
//{x} = {x: 1};
({x} = {x: 1});//1
4)解构赋值的作用
  1. 交换值
let a = 1;
let b = 2;
let c = 3;
[a,b,c] = [b,c,a];
console.log(a,b,c);//2 3 1
  1. 从对象或数组中解构所需要的值
let obj = {
a:{
b:"bbb",
c:"ccc",
d:{
e:"eee"
}
}
};
let {a:{d:{e}},a:{d}}=obj;
console.log(e);//eee
console.log(d);//{ e: 'eee' }
//如果要解构最深层,它的上一级一定要有
console.log(c);//报错,未解构的变量是无法打印的
//解构的时候是一一对应的
  1. 从函数的返回值中解构所需要的值
function f(){
return [1,2,3,4];
}
let [,a,,,b]=f();
console.log(a,b);//2 undefined
  1. 函数参数的解构(支持不完全解构)
function f([a,b,c,d]){
return a+c;
}
console.log(f([1,,7,]));//8
  1. 可以解构map数据结构类型的key-value
let map = new Map();
map.set("a","aaa");
map.set("b","bbb");
// console.log(map);
for(let [index,value] of map){
// console.log(value);
console.log(index)
}
  1. 从指定的模块中解构对应的方法
const {readFile}=require("fs");

三、模板字符串

`字符内容${变量输出}字符内容`

:${ }中的值:

  1. 变量
  2. 任意javascript表达式
  3. 获取对象的属性
  4. 调用函数

四、对象的扩展

1、对象的简写
1)对象属性名的简写
let a="aaa";
let b={a};
console.log(b);//{ a: 'aaa' }、

function f() {
let name="cn";
let age=20;
let sex="女";
return {name,age,sex};//相当于{name:name,age:age,sex:sex}
}
console.log(f());//{ name: 'cn', age: 20, sex: '女' }
2)对象方法名的简写
let a={
f(){
console.log("aaa");
},
f1(){
console.log("aaaaa2");
}
}
//调用
a.f1();//aaaaa2


let aa="haha";
let obj={
a:"saddfsa"
};
let obj2={
[aa]:"sadsfd"
}
console.log(obj2);//{ haha: 'sadsfd' }
console.log(obj2[aa]);//sadsfd
console.log(obj2.haha);//sadsfd


function f(aname) {
return{
[aname]:"cn"
}
}
console.log(f("a").a)//cn

function f(fnname) {
return{
[fnname](){
console.log("我是函数,缺省名字的函数")
}
}
}
console.log(f("aa"));//{ aa: [Function: aa] }
console.log(f("aa").aa);//[Function: aa]
f("aa").aa();//我是函数,缺省名字的函数
2、对象中变量
1)变量做属性名
let name = 'cn';
const a = {
'age':20,
[name]:'cc'//name是一个变量
};
console.log(a['age']);//20
console.log(a[name]);//cc
console.log(a['cn']);//cc
2)变量做方法名
let obj={
['na'+'me'](){
return 'cn';
}
};
obj.name();

五、箭头函数

1、语法

()=>{}

2、参数
1)无参数
let f=()=>{
cnsole.log('a');
}
1)一个参数

可将()省略

let f=n=>{
consle.log('a');
}
1)两个及以上参数
var fu = (n,m=10)=>{
return n*m;
}
3、返回值
1)函数体内是一条语句

{}可省略

let f=n=>console.log(n);
2)函数体内是一条语句,并且是return关键词

省略{}和return

let f=(n,m)=>n*m;
4、使用场景

箭头函数的两个不适用场景:

  1. 对象里面
  2. 事件的回调函数
button.on('click',function(e){
console.log(this)
})
1)回调函数中的箭头函数
let timer=setTimeout(()=>{
console.log(1);
},1000);
2)参数中的箭头函数
function fn(f,a){
console.log(a);
}
fn(()=>{
console.log('我是参数箭头函数');
},10);
5、箭头函数中this的使用规则

箭头函数的this不绑定当前调用者,只与箭头函数定义的上下文环境有关。

1)全局函数中的this
function fun(){
console.log(this);//window 
}
let fun1 = n =>{
console.log(this); //window 
}
2)事件处理函数中的this
let oDiv = document.getElementById("box"); 
oDiv.onclick = function () {
console.log(this);//div
}
oDiv.onclick = ()=>{
console.log(this); //window 
}
3)对象方法中的this
function Person() {
this.eat = function () {
return function () { 
console.log(this); //global
}
}
}
let p = new Person(); 
p.eat()();

function Dog() {
this.eat = function () {
return ()=>{ 
console.log(this); //Dog
} 
}
}
let d = new Dog(); d.eat()();
6、箭头函数的特性
  1. 箭头函数是匿名函数,不绑定自己的this,arguments,super,new.target
  2. 箭头函数会捕获其所在上下文的this值,作为自己的this值,在使用call/apply绑定时,会改变this指向。
  3. 箭头函数不绑定arguments,取而代之用rest参数运算符解决
  4. 箭头函数不能作为构造函数,和 new 一起用就会抛出错误

六、ES6中的运算符

1、rest剩余参数运算符

将以“,”隔开的参数转换为数组
注:剩余参数运算符一定要在形参的最后

function f(b,c,...a) {
console.log(a,b,c);//[3, 4, 5, 6, 7, 8, 9, 10, 11] 1 2
}
f(1,2,3,4,5,6,7,8,9,10,11);
2、spread扩展运算符

将一个数组转为用逗号隔开的参数,通常使用在实参的传递中

用于:给函数传参的时候,不确定传参的个数,并且还要调用的时候

function f(a,b,c,d,e) {
console.log(a,b,c,d,e);// 1 2 3 undefined undefined
}
let arr=[1,2,3];
f(...arr);
1)spread 扩展运算符的应用场景:
  1. 复制、合并数组或对象
    (一维数组:深拷贝;多维数组:浅拷贝)
//复制数组
let arr=[1,2,3];
let arr2=[...arr];//深拷贝(值)
console.log(arr2);//[ 1, 2, 3]

//合并数组
let arr=[1,2,3];
let arr2=[4,5,6];
let newArr=[...arr,...arr2];//合并拷贝,深拷贝(值)
console.log(newArr);//[ 1, 2, 3, 4, 5, 6 ]
  1. 将类似数组或对象转为真正的数组。
let set=new Set();
set.add("aaaa");
set.add("bbbb");
console.log([...set]);//[ 1, 2, 3, 4, 5, 6 ]

七、Symbol

ES第7种数据类型(基本数据类型)

1、定义Symbol类型变量,无参形式

即使使用了参数,参数相当于描述

let a=Symbol();
let b=Symbol();
console.log(a===b);//false
2、Symbol的使用
let a=Symbol();
let obj={
//变量名做属性名
[a]:"hahaha"
}
obj[a]="aaaaaaa";//修改
console.log(obj[a]);//aaaaaaa

let a=Symbol();//生成唯一的哈希值
let b=Symbol();//生成唯一的哈希值
let obj={
[a]:"hahaha"
}
obj[b]="aaaaaaa";
console.log(obj);//两个 { [Symbol()]: 'hahaha', [Symbol()]: 'aaaaaaa' }
3、模拟实现私有属性
function Person() {
let a=Symbol();
let b="bl";
this[a]=()=>{
console.log("我是私有属性");
}
this[b]=()=>{
// this[a]();
console.log("我是单独的方法");
return a;
}
}
const p=new Person();
// console.log(p);//Person { bl: [Function], [Symbol()]: [Function] }
p[p.bl()]();
p.bl();
4、Symbol的for方法可以将两个Symbol定义成同一个Hash
let a=Symbol.for("aaa");
let b=Symbol.for("aaa");
console.log(a===b);//true
console.log(typeof a);//symbol
3、ES6中的Symbol类型有什么作用?

ES6新增了Symbol数据类型,它用来生成一个独一无二的值,Symbol数据常用来给对象属性赋值,让对象属性具备唯一性,不容易被覆盖。

八、Set和Map数据结构

1、Set数据结构

类似数组,与数组的区别在于其内部成员是唯一的(即没有重复元素)。

Set数据结构本身可以去重(数字类型,布尔类型,字符类型)

:同一变量名声明的数组可能去重,在未重新赋值的情况下可以去重,只要重新赋值了即使与原来的值相同也不能去重;不同变量存储的数组不会去重(因为存的是地址)

1)语法
let set = new Set(数组);//注:参数可以省略
2)常用属性
  1. size:获取set结构内元素的数量。
3)常用方法
  1. add(value):添加某个值,返回 Set 结构本身。
  2. delete(value):删除某个值,返回一个布尔值,表示删除是否成功,如果元素不存在代码不会报错可以正常执行
  3. has(value):返回一个布尔值,表示该值是否为Set的成员。
  4. clear():清除所有成员,没有返回值。
  5. forEach:遍历Set结构内的元素。
4)Set用来过滤数组重复数据:let arr = […new Set(arr)];
2、Map数据结构

类似对象,区别在于对象只接受字符串作为键名,而
Map的键名可以是任意类型。

1)语法
let set = new Map(初始化的值);//注:参数可以省略
2)常用属性
  1. size:获取Map结构内元素的数量。
3)常用方法
  1. set(key,value):添加一个键值数据。
  2. get(key):根据key获取value。
  3. has(key):返回一个布尔值,表示map集合是否包含当前key的成员。
  4. delete(key):根据指定的key删除数据。
  5. clear():清除所有成员,没有返回值。
  6. forEach:遍历Map集合使用forEach。

九、Iterator遍历器

1、ES6中的四种数据结构:

数组(Array)、对象(Object)、Map、Set

2、概念

Iterator是一种接口,所以的数据结构只要部署了接口,都可以进行遍历。

作用:循环遍历输出

Symbol.iterator是属性,本身也是封装好的函数,让定义好的数据结构可以遍历

3、ES6中天生可以遍历的:

Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象

4、遍历
let arr=["a","b","c","d","e"];
let it=arr[Symbol.iterator]();//将遍历器属性绑定到自定义的数据结构中,这里定义的变量it相当于一个指针
it.next();//{value:"a",done:false}
it.next();//{value:"a",done:false}
console.log(it.next());//{value:"a",done:false}
//第六次调用it.next()输出 {value:undefined,done:true}

for(let item of it){
console.log(item);//d e
// console.log(item.next());//报错 如果使用for...of遍历遍历器指针,则不能再使用next()方法
}

十、Generator函数

是ES6提供的一种异步编程解决方案,封装了多个内部的状态;

1、Generator函数的定义

定义的关键词:*(用来修饰函数名) 、yield(用来定义状态)

function *f() {
yield "我是状态一";
yield "我是状态二";
yield "我是状态三";
return "我是G函数返回值";
}
2、Generator函数的调用
1)无参
let git=f();
//获取Genertor函数中的状态
//console.log(git.next());//{ value: '我是状态一', done: false }
//console.log(git.next());//{ value: '我是状态二', done: false }

//注:采用for...of循环只能输出generator函数的状态,无法拿到return的返回值
for (let item of git){//Generator函数默认实现了遍历器接口Symbol.iterator
console.log(item);//我是状态一 我是状态二 我是状态三
}

git.next();
git.next();
console.log(git.next());
console.log(git.next());//{ value: '我是G函数返回值', done: true } 拿到return的返回值
console.log(git.next());//此时{value:undefined,done:true} 再继续git.next()都是这个值
2)可以接受参数的next()方法
function * f1() {
let a=yield "我是状态一";
console.log("我是yield一的输出"+a);
let b=yield "我是状态二";//yield "我是状态二";let a="我是next传参二";
console.log("我是yield二的输出"+b);
yield "我是状态三";
return "我是G函数返回值"
}
let gitf1=f1();
//yield关键词本身具备懒惰原理,
//next参数会赋值给上一个状态,使用next()方法传参,yield的懒惰性,会将参数赋值给上一个状态,即是上一个状态的值
console.log(gitf1.next("我是next传参一"));
console.log(gitf1.next("我是next传参二"));
console.log(gitf1.next("我是next传参三"));
3、Generator函数用同步思想解决异步
function * f() {
let a=yield getData();
console.log(a);
}
let fnn=f();
function getData() {
$.get("./user.json").then((data)=>{
//console.log(data);
//f().next(data);//这样写默认看成了f()这个方法的调用
fnn.next(data);
})
}
fnn.next();

十一、Promise对象

Promise和callback一样,目的都是为了异步数据传递,比如ajax请求数据的传递

1、概念

异步编程的一种解决方案,也称之为一个容器,黑箱操作;

2、特点:
  1. 对象的状态不受外界影响;

  2. 一旦状态改变,就不会再变; 状态不可逆 不能互相转换

3、状态:

pending(进行中)、fulfilled(成功)对应的方法resolve()、rejected(失败)对应的方法reject()

4、缺点:
  1. 无法取消Promise;

  2. 不设置回调函数,内部抛出的错误不会反应到外部

  3. pending状态,无法确定进度;

5、对象的实例方法

Promise对象的结果有两个方法:resolve()–已成功(fulfilled) reject()–已失败(rejected)

//1、resolve()
//2、reject()
//例一
function f(){
return new Promise((resolve,reject)=>{
setTimeout(resolve,3000,"我是字符串");//setTimeout的第三个参数是用来给第一个参数赋值的
})
}

//3、then()获取成功状态的值
f().then((data)=>{
console.log(data);//3s后 输出 我是字符串
})
//console.log(f());//Promise { <pending> }

//例二:用伪代码来表示Promise对象的一个状态传值(实例)
function f() {
return new Promise((resolve,reject)=>{
if(1)
resolve("代码执行成功")
else
reject("代码执行失败")
})
}

//例三:
function f() {
return new Promise((resolve, reject) => {
reject("想用失败传值");
})
}
// Promise对象的then方法,参数一是成功的回调函数,参数二是失败的回调函数(通常不建议使用)
f().then((data)=>{
console.log(data);
},(error)=>{
console.log(error)
})

//例四
function f() {
return new Promise((resolve, reject) => {
resolve("想用成功传值");
reject("想用失败传值");
// console.log(a);
// let a = 2;
// throw关键词 抛出关键词 可以抛出自定义错误
// throw new Error("我是自定义的错误!")
})
}
f().then((data)=>{
console.log(data);
}).catch((err)=>{//4、catch()方法可以捕获错误、异常、失败的传值
console.log(err.message);
}).finally(()=>{//5、finally()方法,最终方法,不管Promise对象是成功状态,还是失败状态,还是出现错误,finally方法都会被执行
console.log("我是finally");
})

//6、all()方法
// 当all方法中全部都是成功状态的时候,会以数组的形式输出全部成功的结果;
// 当all方法中存在失败状态的时候,那么它会返回第一个失败的结果;


//7、race()方法:只会返回第一个Promise的状态,不论成功还是失败

十二、async函数

1、简介

async函数,本质就是Generator函数的语法糖;

语法:将Generator函数的*换成async(在function前),将yield换成await;

返回一个Promise对象,可以添加then()方法添加回调函数;

function f() {
return new Promise((resolve,reject)=>{
setTimeout(resolve,3000,"我我");
})
}
async function testAsync() {
let a=await f();//await可以将异步操作同步化。
console.log(a);
}
testAsync()

//async关键词可以独立出现,但是await关键词不能独立出现,如果需要使用await必须用async来修饰函数
async function testAsync2() {
await f();
console.log("aaaaa");
}
testAsync2();
2、async函数中的return关键词
//错误处理
//方法一:
async function f() {
let a=await Promise.resolve("成功执行");
console.log(a);
//当try块中出现错误或异常时,如果采用了catch块捕获,则只会影响try块内部的代码,不会影响其外部的代码
try {
let b=await Promise.reject("我是失败");
console.log(b);
}catch {
//console.log(e);
}finally {
console.log("我是永久执行块")
}
let c=await Promise.resolve("我是成功二");
console.log(c);
return "我是返回值";
}
f().then((data)=>{
console.log(data);
});

//方法二:
//除了采用try...catch进行捕获外,还可以采用Promise对象本身的catch方法,进行捕获。
async function f() {
let a=await Promise.resolve("成功执行");
console.log(a);

let b=await Promise.reject("我是失败").catch((err)=>{
console.log(err);
});
// console.log(b);

let c=await Promise.resolve("我是成功二");
console.log(c);
return "我是返回值";
}
f().then((data)=>{
console.log(data);
});

//方法三:
//优雅处理async。。。await的异常
function f(msg) {
return new Promise((resolve,reject)=>{
//resolve("sssss");
reject(`我是第${msg}次失败`);
})
}
function to(p) {
return p.then((data)=>{return [data,null]}).catch((err)=>{return [null,err]});
}
async function f1() {
//let [data,err]=await f(1)
let [data,err]=await to(f(1));
console.log(data);
console.log(err);
let [data1,err1]=await to(f(2))
console.log(data1);
console.log(err1);
}
f1();

十三、面向对象

1、面向对象编程

本质是以建立模型体现出来的抽象思维过程和面向对象的一些方法。模型是用来反映现实世界中事物理特征。方法是模型所需要的行为动作。

2、面向对象特点:

封装、继承、多态

十四、Class类

1、定义类

关键词class

class 类名 {}

2、类中的元素
1)类的构造方法

关键词:constructor

constructor()方法是类的默认方法,通过new生成对象实例时会自动调用该方法。

作用:1.给变量赋值;2.声明变量

2)成员函数/方法

在成员方法中声明的变量是不能在外面调用的(undefined)

3)成员变量(在类中定义成员变量,变量名直接赋值)

在类中声明成员变量有两种方法:

  1. 变量名=值
  2. this.变量名=值

注:

  • 如果是同一变量名,this可以执行赋值功能
  • 在类的作用域声明的变量,它绑定到类;在构造方法中声明的变量,它也是绑定到类;
  • 如果在方法中使用this绑定到类上的变量,需要调用方法后才能使用,否则不会绑定到类上
  • 如果在类的一个成员方法中使用另一个成员方法中的变量,一点要先调用声明的成员方法才能使用
  • 类中的一个成员方法需要调用另一个成员方法,采用关键词this.成员方法名
class Person {
name = "cn";//类的成员变量

// constructor() {//类的构造方法(是给变量赋值的,声明变量)
// this.name = "cn1";//this关键字代表实例的对象
// }
// 其他语言可以有多个构造方法,但ES6只能有一个构造方法
constructor(name) {
this.name = name;
}

addSmoking(){//类的成员方法
//在成员方法中声明的变量是不能在外面调用的(undefined)
let name1 = "aaa"
this.name2="bbb";

// 类中成员变量的使用需要使用关键词this,如this.name
console.log("我是"+this.name);
}

addSpeaking(){
// 在一个成员方法中调用另一个成员方法,采用关键词this.成员方法名
this.addSmoking();
console.log(this.name2);
}
}

// 类在使用的时候需要实例化
// 注:在给类实例化的时候,会默认调用构造方法,如果构造方法需要参数,需要在实例化的时候传递实参
// 如果没给变量赋值,默认就是undefined
let p = new Person("cn2");
p.addSmoking();

类中两种变量:成员变量、静态变量

三种方法:成员方法、静态方法、构造方法

3、static

调用静态变量:类名.变量名

调用静态方法:类名.方法名

构造方法中不能声明静态变量;
成员方法中,可以使用静态变量和静态方法,必须使用类名调用;
静态方法中,不能使用成员变量和成员方法,但可以使用静态变量和静态方法,调用方式可以是类名也可以是this

class Person {
static age=20;
name="cn";
constructor(){//构造方法
this.age="女";
}
addSmoking(){//成员方法
Person.addListen();
console.log(this.name,this.age);//this.age是undefined,必须要用类名来调用
}
ststic addListen(){//声明静态的方法
console.log("我是静态方法"+this.age);
}
}
let p=new Person();
p.addSmoking();
Person.addListen();//调用静态的方法
Person.age=12;//静态变量的赋值和调用
4、继承

ES6中的继承是完全继承

关键词:extends

存储机制:

内存块中存的是静态方法和静态属性(预加载时存储);成员方法和成员属性在运行时存储

1.子类中可以重新定义父类中的方法和属性,这种形式称之为多态
2.子类中如果需要使用父类的方法,可以采用super关键词调用对应的方法

3.子类不能在成员方法中使用super调用父类的静态方法,会产生运行时错误,可以使用类名里调用父类的静态方法;

4.子类中如果需要使用父类的静态属性,可以使用this
5.子类的构造方法中必须要调用父类的构造方法,语法:super()
6.类中的super关键词指向父类,类的this关键词指向当前类

class Father {
firstName="r";
static sex="男";
constructor() {
this.secondName="p";
}
addSmoking(){
console.log("我是父类中的s");
}
static addDrinking(){
console.log("我是父类中的d");
}
}
class Child extends Father{
firstName="y";
constructor() {
super();//调用父类的构造方法
}
addSmoking() {
//console.log(this.firstName)
//super.addSmoking();
//super.addDrinking();//不能再成员方法中使用super调用父类的静态方法,会产生运行时错误。但是可以使用类名来调用静态的方法
//console.log(this.firstName)
console.log(Father.sex)//可以使用类名来获取静态属性。
Father.addDrinking();
console.log("我是儿子的ns");
}
static addDrinking(){
console.log(this.sex)
super.addDrinking()
console.log("我是儿子的nd");
}
}
const c=new Child();
//c.addSmoking();
// // console.log(c.firstName)
Child.addDrinking();
// console.log(Child.sex)在这里插入代码片
5、属性的修饰符
class A {
username="cn";
//uname是属性名
set uname(value){//set修饰的属性名方法,当给属性名赋值的时候被调用
console.log("我是set修饰的方法")
this.username=++value;
}
get uname(){//get修饰的属性名方法,当输出属性的时候被调用
console.log("我是get修饰的方法")
return this.username;
}
}
// 类必须使用new调用,否则会报错。
const a=new A();
a.uname=123;//调用set修饰的属性名方法
console.log(a.uname);//调用get修饰的属性名方法

十五、数组的扩展

1、静态方法
(1)Array.from()

将对象转化为数组
注:

  1. 只能将key为下标的对象转为数组(支持隐式转换);
  2. 且对象中必须要有length属性,因为新生成的数组需要根据length值来生成元素的个数,
  3. 如果对应下标没有值,则会使用undefined填充;
  4. 如果出现重复下标则会覆盖值;
let obj={1:"aaa",2:"bbb",3:"ccc",length:7,3:"ss",5:"eee"};
console.log(Array.from(obj));
2)Array.of()

将值转化为数组

console.log(Array.of(1,2,3,4,5,"ssss"));
2、成员方法
1)引用.entries()

将数组以[index,value]新数组的形式返回

2)引用.keys()
3)引用.values()
4)引用.includes(值,searchIndex)

查询数组中是否含有参数一的值,返回值是布尔类型;

参数二是开始查找的下标(包含起始下标),负值:从最大长度开始往左数参数个

includes()方法可以实现模糊搜索,但是区分大小写

5)find()

也是查找,查找数组中满足回调函数中return条件的第一个元素

6)some()

搜索当前数组中是否含有满足回调函数返回值的值,如果有返回true,没有返回false

7)every()

搜索当前数组中的值必须全部都满足回调函数的返回值,满足返回true,否则返回false在这里插入代码片

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值