ES5_6_7之ES6
网页版文档:link
1.1let和const关键字
2.模板字符串
let obj={
user:'web',password:'123'};
let str=`用户名为:${
obj.user},密码为${
obj.password}`;
console.log(str);
3.箭头函数
<script>
// 形参的情况
// 1.没有参数
let fun = () => console.log('我是没有形参的箭头函数fun');
fun();
// 2.有一个形参,此时的括号可以省略
let fun1 = a => console.log('我是有一个形参的箭头函数fun1');
fun1();
// 3.有两个或者多个形参的时候,括号不可以省略
let fun2 = (a, b) => console.log(Math.pow(a, b));
fun2(2, 3);
// 4.函数体的情况
// -1.函数体只有一条语句或者表达式的时候,{}可以省略
let fun3 = (a, b) => a + b;
console.log(fun3(20, 30));
// -2.多个语句或者表达式时,{}不可以省略
let fun5 = (a, b) => {
console.log(Math.sqrt(a, b));
return a + b;
};
fun5(9, 3);
// 箭头函数this验证
// 1.普通函数的this
let fun6 = function () {
alert(this) };
fun6();
// 2.箭头函数的this,指向window
let fun8 = () => {
console.log(this) };
fun8();
let btn = document.getElementById('btn');
let fun9 = {
name: 'kf',
// 外层是箭头函数,指向window,
// getName:()=>{
// btn.οnclick= ()=>{console.log(this)};
// }
// 外层是普通函数,指向外层this
getName: function () {
btn.onclick = () => {
console.log(this) };
}
}
fun9.getName();
</script>
4.三点运算符
arguments:
在调用函数时,浏览器每次都会传递进两个隐含的参数
1.函数的上下文对象 this
2.封装实参的对象 arguments
-arguments是一个类数组对象,他也可以来通过索引操作数据,可以获取长度
-在调用函数时,我们所调用的实参都会保存在arguments中
-arguments.length可以用来获取实参的个数(长度)
-即使我们不定义形参,也可以通过arguments来使用实参
arguments[0] 表示第一个实参
arguments[1] 表示第二个实参
arguments[2] 表示第三个实参
-arguments中的一个属性callee
这个属性对应的是当前正在指向的函数的对象
<script>
// 三点运算符 语法: ...变量
// 属于rest(可变)参数,用来取代arguments,但比arguments更加的灵活
// (a,b,...变量)三点运算符必须放在形参的最后的位置
function fun(...value) {
console.log(arguments);
console.log(value);
// arguments不能使用foreach来遍历数组,但是三点运算符可以
value.forEach(function (item, index) {
console.log(item, index) });
}
fun(1, 2, 3);
// 应用
let arr=[1,6];
let arr1=[2,3,4,5];
arr=[1,...arr1,6];
// 输入数组arr
console.log(arr);
// 输出数组中的每一个元素
console.log(...arr);
</script>
5.Promise对象
1.理解
-Promise对象:代表了未来某个将要发生的事件(通常是一个异步操作)
-有了promise对象,可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数
-ES6的Promise是一个回调函数,用来生成Promise实例
2.使用promise基本步骤(2步):
-1.创建promise对象
-2.调用promise的then
3.promise对象的三个状态:
-pending 初始化状态
-fullfilled 成功状态
-rejected 失败状态
4.应用:
-使用promise实现超时处理
-使用promise封装处理ajax请
<script>
// 1.创建promise对象
let promise =new Promise((resolve,reject)=>{
// 初始化promise状态: pending 初始化
console.log('111');
// 执行异步操作,通常是发送ajax请求,开启定时器
setTimeout(() => {
// 根据异步任务返回结果去修改promise的状态
// 1.异步任务执行成功,修改promise状态为fullfilled
resolve('2020/11/23/22:51');
// 2.异步任务执行失败,修改promise状态为rejected
reject();
}, 2000);
})
console.log('222');
// 2.调用promise实例对象的一个方法then
promise.then(
// 成功的回调函数,data获取resolve()执行成功后的数据
(data)=>{
console.log(data,'成功了...')},
// 失败的回调函数,error获取rejected()的数据
(error)=>{
console.log(error,'失败了...')})
</script
6.Symbol属性介绍
ES5中对象的属性名都是字符串,容易造成重名,污染环境
Symbol:
概念:ES6中添加了一种新的原始数据类型Symbol(已有的原始数据类型:String Number null boolean undefined 对象)
特点:
1.Symbol属性对应的值是唯一的,解决命名冲突问题
2.Symbol值不能与其他数据进行计算,包括同字符串拼串
3.for in , for of在遍历时不会遍历Symbol属性
<script>
// 1.使用Symbol函数得到Symbol属性值
let symbol=Symbol();
let obj={
name:'KFC',age:18};
// 添加Symbol属性并设置属性值
obj[symbol]='12138';
console.log(obj);
// 2.传参标识
let symbol2=Symbol('one');
let symbol3=Symbol('two');
console.log("symbol2与symbol3的值是否相等:"+(symbol2==symbol3));
// 3.内置Symbol值
// -除了定义自己使用的Symbol值外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法
// -Symbol.iterator 对象的Symbol.iterator属性,指向该对象的默认遍历器方法
let targetData={
[Symbol.iterator]:function(){
// 记录指针的位置
let nextIndex=0;
return {
next:function(){
return nextIndex<this.length?{
value:arr[nextIndex++],done:false}:{
value:undefined,done:true}
}}
}
}
// 4.for in /for of不能遍历Symbol属性
for(let i in obj){
console.log(i);
}
</script>
7.iterator迭代机制
概念:iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
1.为各种数据结构提供统一的简便的访问接口
2.使得数据结构的成员按照某种次序排列
3.ES6创造了一种新的遍历命令for of循环,iteration主要供for of 消费
工作原理:
1.创建一个指针对象(遍历器对象),指向数据结构的起始位置
2.第一次调用next方法,指针自动指向数据结构的第一个成员
3.接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
4.每次调用next方法返回的是一个包含value和done的对象
-value表示当前成员的值,done对应的布尔值表示当前的数据结构是否遍历结束
-当遍历结束的时候,value值是undefined,done值为true
扩展理解:
1.当数据结构上部署了Symbol.iterator,该数据就可以用for of遍历
2.当使用for of遍历目标数据时,该数据会自动寻找Symbol.iterator属性
3.当使用三点运算符/解构赋值时,会默认自动调用iterator接口
<script>
// 模拟指针对象(迭代器对象)
function myIterator(arr){
// 记录指针的位置
let nextIndex=0;
return {
next:function(){
return nextIndex<arr.length?{
value:arr[nextIndex++],done:false}:{
value:undefined,done:true}
}}
}
// 要传入的数据
let arr=[1,3,5,'a','b'];
let iterator1=myIterator(arr);
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
// 将iterator接口部署到指定的数据类型上,就可以用for of去循环
// 数组,字符串,arguments,set容器,map容器
for(let i of arr){
console.log("数组for of遍历:"+i);
}
// 字符串
let str='defg';
for(let i of str){
console.log("字符串for of 遍历:"+i);
}
// arguments
function fun(){
for(let i of arguments){
console.log(i);
}
}
// argumnets传入实参
fun(1,2,'KF');
</script>
8.Generator函数
Generator函数:
概念:
1.ES6提供的解决异步编程的方案之一
2.Generator函数是一个状态机,内部封装了不同状态的数据
3.用来生成遍历器对象
4.可暂停函数(惰性求值),yield可暂停,next可启动,每次返回的是yield后的表达式结果
特点:
1.function与函数之间有一个星号
2.内部用yield来定义不同的状态
3.generator函数返回的是指针对象,而不会执行函数内部逻辑
<script>
// 3.generator函数返回的是指针对象,而不会执行函数内部逻辑
function* myGenertor(){
console.log("开始执行,死亡之手发动!");
// yield可暂停 next 可启动
// 从哪里暂停就从哪里启动,启动时传入的参数将作为暂停时的返回结果
let y= yield 'Hello';
console.log(y);
yield 'World';
return '设置yield的返回值'
}
// 返回的是指针对象(迭代器对象)
let mg=myGenertor();
// 调用指针对象的next()方法
console.log(mg.next());
console.log(mg.next('作为yield的返回值'));
console.log(mg.next());
// 对象的Symbol.iterator属性指向遍历器对象
// 当使用for of遍历或者迭代时,会自动调用迭代器的next()方法
let obj={
name:'zxy',age:20};
obj[Symbol.iterator]=function* myTest(){
yield 1
yield 2
yield 3
}
for(let i of obj){
// 将会遍历到 1 2 3
console.log(i);
}
</script>
9.async函数
async函数:
概念:真正意义上去解决异步回调的问题,同步的流程表达一步的操作
本质:Generator的语法糖
语法:
async function foo(){
await 异步操作;
await 异步操作;
}
特点:
1.不需要Generator那样去调用next方法,遇到await等待,当前的异步操作完成就往下执行
2.返回的总是Promise对象,可以用then方法进行下一步操作
3.async取代Generator的*,await取代Generator的yield
4.语义上更为明确,使用简单,经临床验证,暂时没有任何副作用及不良反应
<script src="jquery-3.5.1.min.js"></script>
<script>
async function foo(){
return new Promise(resolve=>{
setTimeout(resolve,2000);
})
}
async function test(){
console.log("开始执行...",new Date().toTimeString());
await foo();
console.log("执行完毕...",new Date().toTimeString());
}
test();
// async里的await返回值
// 1.
function test2(){
return '我是普通函数的返回值';
}
async function test3(){
let t2=test2();
console.log(t2);
}
test3();
// 2.
async function test5(){
let result=await Promise.resolve("传入的参数作为返回值");
console.log(result);
}
test5();
</script>
10.class类使用
1.通过class定义类/实现类的继承
2.在类中使用constructor定义构造方法
3.通过new来创建类的实例
4.通过extennds来实现类的继承
5.通过super来调用父类的构造方法
6.重写从父类中继承的一般方法
<script>
// 使用constructor定义构造方法
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
// 类的一般方法
showName(){
console.log(this.name+" "+this.age);
}
}
let p1=new Person('zly',22);
console.log(p1);
p1.showName();
// 类的继承
class extendsClass extends Person{
constructor(name,age,salary){
// 首先要调用父类的构造方法
super(name,age);
this.salary=salary;
}
// 重写父类的方法
showName(){
console.log(this.name,this.age,this.salary);
}
}
let test1=new extendsClass('张伟',30,20201208);
console.log(test1);
</script>
11.字符串,数值的扩展
字符串:
1.includes(str) 判断是否包含指定的字符串
2.startsWith(str) 判断是否以指定的字符串开头
3.endsWith(str) 判断是否以指定的字符串结尾
4.repeat(count) 重复指定次数
数值:
1.二进制与八进制数值表示法:二进制用0b,八进制用0o
2.Number.isFinite(i) 判断是否有限大的数
3.Number.isNaN(i) 判断是否是NaN
4.Number.isInteger(i) 判断是否是整数
5.Number.parseInt(i) 将字符串转换为对应的数值
5.Math.trunc(i) 直接去除小数部分
<script>
// 字符串
let str='abcdef';
console.log(str.includes('d'));
console.log(str.startsWith('ab'));
console.log(str.endsWith('def'));
console.log(str.repeat(3));
// 数值
console.log(0b1010);
console.log(0o56);
console.log(Number.isFinite(Infinity));
console.log(Number.isNaN(NaN));
console.log(Number.isInteger(12138.0));
console.log(Number.parseInt('abc123'));
console.log(Math.trunc(3.1415926));
</script>
12.数组,对象方法的扩展
数组:
1.Array.from(v) 将伪数组对象或者可遍历的对象转换成真正的数组
2.Array.of(v1,v2,v3) 将一系列值转换成数组
3.find(function(value,index,arr){return true}) 找出一个满足条件返回true的元素
4.findIndex(function(value,index,arr){return true}) 找出一个满足条件返回true的元素下标
对象:
1.Object.is(v1,v2) 判断两数是否相等
2.Object.assign(target,source1,source2,...) 将源对象的属性复制到目标属性上
3.直接操作__proto__属性
<script>
let btns=document.getElementsByTagName('button');
// 1.Array.from(v) 将伪数组对象或者可遍历的对象转换成真正的数组
Array.from(btns).forEach(function(item,index){
console.log(item);
})
// 2.Array.of(v1,v2,v3) 将一系列值转换成数组
let arr=Array.of(1,2,3,'abc',true);
console.log(arr);
// 3.find(function(value,index,arr){return true}) 找出一个满足条件返回true的元素
let arr1=[1,2,3,4,5,6,7,8];
let result= arr1.find(function(item,index){
return item>5;
})
console.log("符合查找条件的第一个元素为:"+result);
// 4.findIndex(function(value,index,arr){return true}) 找出一个满足条件返回true的元素下标
let result1= arr1.findIndex(function(item,index){
return item>5;
})
console.log("符合查找条件的第一个元素的下标为:"+result1);
// 对象
// 1.Object.is(v1,v2) 判断两数是否相等
console.log(0==-0);//true
console.log(NaN==NaN);//false
console.log(Object.is(1,-1));//false
console.log(Object.is(NaN,NaN));//true
// 2.Object.assign(target,source1,source2,...) 将源对象的属性复制到目标属性上
let obj={
};
let obj1={
name:'tom',age:18};
let obj2={
gender:'male'};
Object.assign(obj,obj1,obj2);
console.log(obj);
// 3.直接操作__proto__属性
let obj3={
};
obj3.__proto__={
obj1,obj2};
let obj5={
};
obj5.__proto__=obj2;
console.log(obj3);
console.log(obj5);
</script>
13.对象的拷贝(克隆)
拷贝数据:
基本数据类型
拷贝后会生成一份新的数据,修改拷贝后的数据不会影响原数据
数组/对象
拷贝后不会生成新的数据,而是拷贝的引用,会影响原来的数组
拷贝数据的方法:
1.直接复制给一个变量 //浅拷贝
2.Object.assign //浅拷贝
3.Array.prototype.concat() //浅拷贝
4.Array.prototype.slice() //浅拷贝
5.JSON.parse(JSON.stringify()) //深拷贝,拷贝的数据里不能有函数,处理不了
<script>
// 1.不会影响原数组
let str='abc';
let str1=str;
str='';
console.log(str);
console.log(str1);
console.log("--------------");
// 2.会影响原数组
let obj={
name:'siri',age:12};
let obj1=obj;
obj1.age=18;
console.log("obj:"+obj.name+obj.age);
console.log("obj1:"+obj1.name+obj1.age);
// 拷贝数组/对象,不是生成新的数据而是复制了一份引用
let arr=[1,2,'mn',{
name:'icco',price:2999}];
let arr1=[];
arr1=arr;
console.log(arr1,arr);
arr1[2]='ko';
console.log(arr1,arr);
console.log("--------------");
// 2.Object.assign
let obj2={
id:1,price:1999};
let obj3=Object.assign(obj2);
console.log(obj3,obj2);
obj3.id=2;
console.log(obj3,obj2);
console.log("--------------");
// 3.Array.prototype.concat()
let arr2=[5,6,{
salary:10000}];
let arr3=arr2.concat(arr);
console.log(arr2,arr3);
arr3[1]=2;
console.log(arr2,arr3);
console.log("--------------");
// 4.Array.prototype.slice(start,end) //浅拷贝
let arr5=arr2.slice();
console.log(arr5,arr2);
arr5[0]= 8;
console.log(arr5,arr2);
// 5.JSON.parse(JSON.stringify()) //深拷贝
console.log("--------------");
let arr6=JSON.parse(JSON.stringify(arr));
console.log(arr6);
arr6[0]=5;
console.log(arr6,arr);
</script>
深度克隆:
即使有对象/数组,也可以继续遍历对象/数组里的每一项值,一直拿到的是基本数据类型,再去复制,就是深度拷贝
如何判断数据类型:
1. typeof返回的数据类型:String Number Undefined Object Function Boolean
2.Object.prototype.toString.call(obj)
// 定义检测数据类型的函数
function checkType(target){
return Object.prototype.toString.call(target).slice(8,-1);
}
// 实现深度克隆-->对象/数组
function clone(target){
// 判断数据类型
let result,targetType=checkType(target);
if(targetType==='Object'){
result={
};
}else if(targetType==='Array'){
result=[];
}else{
return target;
}
// 遍历目标数据
for(let i in target){
// 遍历数据结构的每一项值
let value=target[i];
// 判断目标数据是否存在数组/对象
if(checkType(value)==='Object'||checkType(value)==='Array'){
// 继续遍历获取到的value1值
result[i]= clone(value);
}else{
result[i]=value;}
}
}
let arr10=[6,7,8,{
level:52,price:999}];
let arr11=clone(arr10);
console.log(arr10);
arr11[3].level=100;
console.log(arr11,arr10);
14.Set容器,Map容器
set容器: 无序不可重复的多个value的集合体
Set()
Set(array)
add(value)
delete(value)
has(value)
has(value)
clear()
size
Map容器: 无序的key不重复的多个key-value的集合体
Map()
Map(array)
set(key,value)
get(key)
has(key)
delete(key)
clear()
size
for(let value of target){}循环遍历
1.遍历数组
2.遍历Set/Map
3.遍历字符串/伪数组
<script>
let set=new Set([1,2,3,9,8,7,6]);
console.log(set);
set.add(11);
console.log(set.size,set);
console.log(set.has(9));
// set.clear();清空
// console.log(set);
let map=new Map([['abc','username',25],[18,'age']]);
console.log(map);
map.set(24,'wangming');
console.log(map);
map.delete(25);
console.log(map);
</script>
ES5_6_7之ES7:
1.指数运算符(幂) **
2.Array.prototype.includes(values) 判断数组中是否包含指定值value
<script>
console.log(3**3);
let arr=[1,2,3,'TNT'];
console.log(arr.includes('T'));
</script>