ES6基础教程

ES6

模板字符串

  • 模板字符串格式
var age = 33;
var str= = `我叫陈哥`
console.log(`我叫陈哥,今年${age}`)
  • 模板字符串特点

let

  • 什么是let?
    let用于代替var,用于声明变量的新关键词,不会存在变量提升

  • var的两个缺点

  1. 变量声明提前,打乱了程序正常的执行顺序
  2. 没有块级作用域,代码块内的变量,会影响块外的变量
  • 变量提升举例
for(let i = 0;i<10;i++){
	console.log(i)//0-9
}
console.log(i)//报错
//以后写程序都用let不用var 只要声明变量都用let代替var
  • let原理

  • let会被自动翻译为匿名函数自调

  • 双保险,let为了进一步避免可能的冲突将变量悄悄改了名字:let t = 0 —> let _t = 0;

  • let特点

  • 全局写let t=0,用window.t却找不到

  • 同一级作用域内,不能在 let t=0 前,提前使用t。即使外层作用域有t变量,也不行

  • 相同作用域内,不允许重复let同一个变量

  • 注意事项:let有个兄弟const,专门用于声明一个值不能修改的常量。同时也具有let的特点,不会被声明提前,添加了块级作用域

  • 案例:

//第一步获得button按钮
    var btn = document.getElementsByTagName("button");
    // 用var
    //{}并不是块级作用域,全局依然可以找到
    //使用var声明的变量时在全局下,当我们开始找的时候,就已经在全局之下执行完成for循环了
    for(var i=0;i<btn.length;i++){
      btn[i].οnclick=function(){
        console.log(`点击了第${i+1}个按钮`)
      }
    }
    // 用let
    for(let j=0;j<btn.length;j++){
      btn[j].οnclick=function(){
        console.log(`点击了第${j+1}个按钮`)
      }
    }

箭头函数

  • 箭头函数如何使用
  1. 去掉 function,在 () 和 {} 之间加 =>
  2. 当形参只有一个的时候可以省略()
  3. 当函数内部是return时,可以省略return不写
  4. 当函数内部只有一条语句时,可以省略{}(就像if语句省略{}一个道理)
  • 数组排序
//funtion(){}
var arr = [1,2,5,3,4,6];
arr.sort((a,b)=>{
	return a-b
})
//当只有一个参数的时候可以省略()
console.log(arr)
  • 简化:
 //箭头函数
    function show(a){
      a(1)
    }
    // show(function(b){
    //   console.log(b)
    // })
    //简化
    // show((b)=>{
    //   console.log(b)
    // })
    //简化
    show(a=>console.log(b))
  • 什么时候使用?
    几乎所有回调函数都可以用 => 来简化
    注意:一定要记得去掉结尾的分号
  • 箭头函数的问题:
    箭头函数是一把双刃剑,箭头函数内外this是相通的。如果希望函数内外的this保持一致时,可以不用bind()换,而直接改为箭头函数即可。如果不希望函数内外的this一致,就是希望内部的this和外部的this不一样时,不能改为箭头函数
//this->window
var lilei={   //不是作用域
   sname: "Li Lei",
   friends:["欣欣","峰峰","丁丁"],
   // say:function(){
   say(){
	 // 今后ES6中所有对象的方法不用加":function"
       // 但是这个简写不改变this,绝不等于箭头函数
       // Li Lei认识欣欣
       // Li Lei认识峰峰
       // Li Lei认识丁丁
       // 遍历lilei好友列表中每个朋友
       this.friends.forEach(
            // function(f){console.log(`${this.sname}认识${f}`)}
            //函数内的this指向window,用bind改变this的指向
            f=>console.log(`${this.sname}认识${f}`)
           // 希望this和say中的this保持一致都指lilei
    )
  }
}
lilei.say();
var button = document.getelementbyid("button")
button.addEventListener(functon(){
	console.log(this)
	}//this指向button
button.addEventListener(()=>{
	console.log(this)
	}//this指向window

for of

var li = document.querySelectorAll("#ul>li");
    var str = "hello word";
    var arr = [2,4,5,9,3];
    var obj={
      name:"kiki",
      age:12
    }
    for(var key of arr){
	    console.log(key)
    }
  • 对比循环
  1. for循环
  2. arr.forEach()
  3. for of 局限:无法获得当前遍历的位置;是ES6的功能,不是所有浏览器,所有数组和类数组对象都支持
    for of和for循环一样的,可以遍历数组、类数组对象、字符串,但是不能遍历对象和关联数组
  4. for in 只能遍历关联数组和对象,in其实不仅遍历当前对象自己的成员,且会延着原型链向父对象继续查找所有可用的成员名
  • for循环、for of、forEach三种遍历,哪种效率高?
    答:一样高。其实只有一种遍历,就是for循环。其他的都是封装的for循环而已。所以,ES5的其他遍历函数 indexOf、every、some、forEach、 map、filter 和 reduce,都没有效率的提升,因为内部都是for循环而已,只是语法简单而已

  • 是不是有了ES6,就不用ES5了?
    答:要看浏览器是否兼容ES6。如果使用框架和微信开发,基本上可以使用最新的语法。因为框架中和微信开发中都自带翻译工具(Babel),在项目打包时,会将ES6代码翻译成ES5代码,保证浏览器兼容性。如果没使用框架,使用原生或jquery开发,则尽量不要使用ES6

参数增强

  • 参数默认值
  1. 什么是参数默认值(default)?
    ES6允许为函数定义中形参列表的最后一个参数定义默认值,如果没有传递实参,则自动调用形参的默认值
    function fn(a,b,c=0){…}
  2. 使用
    定义:function 函数名(形参1,形参2,…,形参n=默认值)
    提示:如果调用函数时,没有提供最后一个实参,就自动用默认值代替
//形参默认值
    function add(a,b,c=10){
      console.log(a+b+c)
    }
    add(1,2,3)//6
    add(1,2)//13
调用函数时,如果没有传入最后一个实参值,则自动使用默认值代替

兼容性写法:

function add(a,b,c){
      //兼容性写法
      c=c||10
      //或者写  c === undefined && (c=10)
      console.log(a+b+c)
    }
    add(1,2,3)//6
    add(1,2)//13

案例

//点餐案例
    function order(zhushi,xiaochi,yinliao="可乐"){
      console.log(`您点的套餐为:
        主食:${zhushi}
        小吃:${xiaochi}
        饮料:${yinliao}
      `)
    }
    order("米饭","鸡腿")
  • 剩余参数
    专门代替arguments的语法,代替arguments处理不确定参数个数的情况
  1. 定义函数时
    从头到尾获得所有实参值
    function fun(…数组名){…}
    提示:…的意思是”收集”,把传给函数的所有实参值都收集到…后的数组中保存
//剩余参数
    var arr=[]
    function order(...arr){
      console.log(arr)
    }
    order("套餐1","套餐2","套餐3")

剩余参数可以只收集部分实参值
function 函数名(形参1,形参2,…数组名){…}
提示:…数组名 收集的是除了之前形参1和形参2对应的实参值之外的所有剩余的实参值
注意:保存剩余实参值的结构是一个纯正的数组,可用数组家全部APi

var arr=[]
    function order(taocan1,taocan2,...arr){
      arr.forEach(function(elem,i){
        console.log(elem+i)//元素值+下标
      })
    }
    order("套餐1","套餐2","套餐3","套餐4")//套餐32套餐43

案例1:使用剩余参数语法求和

var arr=[];
    function add(...arr){
      console.log(arr)
      var result = arr.reduce(function(prev,elem,i,arr){
        return elem+prev;//prev是前一个参数,elem是当前参数值
      })
      return result;
    }
    console.log(add(1,2,3,4))//10

案例2:计算员工薪资,包含姓名和基本工资(bonus),以及其他来源工资(送外卖,跑滴滴,兼职…),使用剩余参数来实现

var arr=[];
    function add(name,jibengongzi,...arr){
      var result = arr.reduce(function(prev,elem){
        return prev+elem
      })
      var sum=result+jibengongzi
      // return sum;
      console.log(`${name}的总工资是${sum}`)
      // return `${name}的总工资是${sum}`
    }
    // console.log(add("lili",2000,1,2,3,4))
    add("lili",2000,1,2,3,4)
//用for循环做
var arr=[];
    function add(name,jibengongzi,...arr){
      // var result = arr.reduce(function(prev,elem){
      //   return prev+elem
      // })
      // var sum=result+jibengongzi

      // //用for循环做
      for(var i=0;i<arr.length;i++){
        var result=result+arr[i]
      }
      var sum = result+jibengongzi;
      // return sum;
      console.log(`${name}的总工资是${sum}`)
      // return `${name}的总工资是${sum}`
    }
    // console.log(add("lili",2000,1,2,3,4))
    add("lili",2000,1,2,3,4)
    add("bibi",3000,1,2,3,4,5)
  • 打散数组
    什么是打散数组?

    将一个数组打散为多个元素值,依次传给函数的多个形参变量,代替apply

    为什么使用打散数组?

    apply()也能打散数组参数,再传给要调用的函数。但是,apply()的本职工作是修改this,然后顺便帮忙打散数组。如果今后我们只想单纯的打散数组,跟this无关时。apply()就不好用了。如果用apply()单纯打散数组,必须给定一个无意义的对象作为第一个参数
    Math.max.apply( ? ,arr)

    var arr=[4,6,2]
    console.log(Math.max.apply(null,arr))//(this指针的方向,数组)

什么时候使用打散数组?

当一个函数不支持数组参数,而给定的实参值却是放在一个数组中的时候,都要先打散数组,再使用多个值
Math.max(…arr)

…先将数组打散为单个值,再传入前边的函数。好处是,…和this无关,只是专门单纯的打散数组

使用打散数组
(要考)
函数名(…数组)

复制数组:
第一种:var arr1 = arr.slice();
第二种: var arr1=[…arr]

合并两个数组
第一种: var arr3=[].concat(arr1,arr2)
第二种: var arr3=[…arr1,…arr3]

浅克隆一个对象
var obj1 = {…obj}

合并两个对象
第一种: var obj3 = Object.assign({},obj1,obj2)
将obj1和obj2打散后,所有的属性,都放入第一个参数空对象中返回
Object.assign方法用于对象的合并,第一个参数是目标对象,后面的参数都是源对象

第二种: var obj3={…obj1,…obj2}
笔试题:

  1. …不是打散的意思吗?这里怎么成了收集?

    定义函数时,形参列表中的…是收集不确定个数的实参值的意思。调用函数时,实参值列表中的…是打散数组实参为多个实参值,分别传入的意思

  2. …作为打散数组放在实参列表中时,不一定放在结尾?

    是的,可以和其他单独的实参值混搭

解构

  1. 什么是解构(destruct)?
    将一个大的对象或数组中集中存储的成员中的个别成员,取出来单独使用

  2. 为什么要使用解构?
    将来从服务器端返回的对象或数组可能很复杂

  3. 什么时候使用解构?
    凡是获得结构嵌套非常复杂的对象,都要先解构成多个小的成员,再分别单独使用

  • 数组解构:
    同时声明多个变量,下标对下标,去数组中找到和当前变量所在下标一致的元素值,保存到对应位置的变量中,从此变量1和变量2就可代表数组中的单个元素,单独使用
var [cg,zx,qg]=[[1,2,3],[4,5,6],[7,8,9]]
//    0  1  2
console.log(cg)//[1,2,3]
//不声明第三个变量,交换两个变量的值
    var change = [1,2];
    var [a1,b1]=change;//[a,b]
    change = [2,1];
    var [a1,b1]=change;
    console.log(a1)//2
  • 对象解构
var {name:name,sex:sex}={
      name="cg",
      sex="女"
    }
  1. 什么是对象解构?
    仅提取出复杂对象中的个别成员属性或方法,保存在变量中,单独使用
  2. 简写简写形式:如果属性名和变量名相同,只写一个即可
var {sname:sname, signin:signin}=lilei
var {sname, signin}=lilei
 var obj={
      name:"陈小玲玲",
      sex:"女",
      say1:function(){
        console.log(`我是${name}`)
      },
      say2:function(){
        console.log(`我是个${sex}的`)
      }
    }
    var {sex:sex,say1:say1,name:name}=obj//对象解构顺序无限制
    console.log(sex)
    say1()//我是陈小玲玲
  • 参数解构
 function xiaomeng({
      name:name,
      age:age//当属性名和形参名一致时才可以简写:name,age,简写只能出现在函数定义中,函数调用时必须使用函数参数解构 的完整形式
    }){
      console.log(name,age)
    }
    //调用
    xiaomeng({
      name:"叶梦",
      age:18,
    })
//点餐系统
    function order({zhushi="小龙虾鸡肉卷",xiaochi="香辣鸡翅",yinliao="可乐"}){
      console.log(`
        您点的套餐为:
        主食:${zhushi}
        小吃:${xiaochi}
        饮料:${yinliao}
      `)
    }
    //默认情况下,一个都不选择,直接选择套餐
    order({})
    //想要换掉饮料
    order({
      yinliao:"奶茶"
    })
    //想要换掉小吃和饮料
    order({
      xiaochi:"鸡米花",
      yinliao:"奶茶"
    })
    order({
      zhushi:"米饭",
      xiaochi:"鸡腿",
      yinliao:"雪碧"
    })

其实就是对象解构在函数传参时的应用而已

class封装

  • 使用
// 1. 用class{}包裹构造函数和原型对象方法
class Student{
    // 2. 构造函数名提升为整个类型class名,所有构造函数统一更名为constructor
    constructor(sname,sage){
           this.sname=sname;
           this.sage=sage;
    }
    // 3. 所有原型对象方法可省略一切前缀和=function。定义在class中的普通函数,默认就是保存在原型对象中的
    intr(){
           console.log(`我是 ${this.sname}, 我今年 ${this.sage} 岁`)
   }
}
var stu=new Student("lili",22)
//class封装
    class Student{
      //构造函数的名以class进行提升
      //所有构造函数中的变量,统一保存在constructor中
      constructor(name,sex){
        this.name=name,
        this.sex=sex
      }
      //所有原型对象中的属性和方法都省略 xxx.prorotype.xxx=function
      init(){
        console.log(`${this.name}是个大镁铝,今年${this.sex}岁`)
      }
    }
    var stu = new Student("陈小玲玲",19)
    stu.init()

注意:在clas中强烈不推荐共有属性
但是我们还是写一下

//class封装
    class Student{
      constructor(name,age){
        this.name=name;
        this.age=age;
        if(Student.prototype.sex==undefined){
          Student.prototype.sex="女"//所有构造函数里的属性,将来一律都会成为每个子对象的自有属性
        }//在构造函数中,向原型对象中添加共有属性。强调一点,要先判断原型对象中如果没有这个共有属性,才强行添加。如果已经有这个共有属性了,则不要再重复添加
        Student.prototype.ClassName="大四2班"//在原型上添加,但是,我们每次执行的时候都会重复执行
      }
    }
    console.log(stu.ClassName)
    var stu1 = new Student("cxll",20)
    stu1.ClassName="高一6班"
    console.log(stu1.age)//20
    console.log(stu1.ClassName)//高一6班
  • 访问器属性(用来保护子对象)
"use strict";
class Emp{
      constructor(eid,ename,eage){
            this.eid=eid;
            this.ename=ename;
            this.eage=eage;
            // 要保护的是将来要创建的子对象
            Object.defineProperties(this,{
                    eid:{ writable:false },
                    // 1. 定义一个隐姓埋名的半隐藏的数据属性
                    _eage:{
                          value:eage,
                          writable:true,
                          enumerable:false
                    }
            })
            // 密封将来要出生的子对象
            Object.seal(this);
     }
     // 向该类型的原型对象中添加一个访问器属性eage,包含两个保镖函数get和set
     get eage(){
          return this._eage;
     }
     set eage(value){
          if(value>=18&&value<=60){
               this._eage=value
          }else{
               throw Error("年龄必须介于18~60之间")
          }
     }
}
var lili=new Emp(1001, "lili", 25);
// 试图修改eid属性
// lili.eid=0;
// 试图删除ename属性
// delete lili.ename
// 试图修改eage为-2
// lili.eage=-2;
console.log(lili);
var xinxin=new Emp(1002,"xinxin",26);
// 试图修改eid属性
// xinxin.eid=0;
// 试图删除ename属性
// delete xinxin.ename
// 试图修改eage为-2
// xinxin.eage=-2;
console.log(xinxin);

清楚案例:

class Student{
      constructor(name){
        this.name=name;
        this.age=20;
        //添加年龄
        Object.defineProperties(this,{
          _age:{
            value:this.age,
            writeable:true,
            configurable:false
          }
        })
        if(Student.prototype.sex==undefined){
          Student.prototype.sex="女"
        }
      }
      //访问
      get age(){
        return this._age;
      }
      //设置
      set age(value){
        if(value>=18&&value<=80){
          return this._age = value
        }else{
          throw Error("超出范围")
        }
      }
      init(){
        console.log(`${this.name}是个大镁铝,今年${this.age}岁`)
      }
    }
    var stu1 = new Student("cxll")
    console.log(stu1.age)
  • class继承
//1.我们得有一个父对象,父对象包汉子对象想要的东西(相同的属性和结构)
    class Father{
      constructor(money,house){
        this.money=money;
        this.house=house
      }
      say(){
        console.log(`我是你爸爸,我真伟大`)
      }
    }
    //2.继承
    class Child extends Father{
      
    }
    var child1 = new Child(1000,"you");
    console.log(child1.money)

飞机大战

super:通过super把X,Y的值传递给父对象,而super本身相当于调用父对象的构造函数
extends附赠了一个关键词super,super指向父类型的构造函数。调用super,就等效于调用父类型的构造函数了

//飞机大战数据结构

    //敌军或奖励的位置
    class Diren{
      constructor(x,y){
        this.x = x;
        this.y = y;
      }
      fly(){
        console.log(`敌军位于(${this.x},${this.y})的位置`)
      }
    }
    //击落敌军得分
    class Score extends Diren{
      constructor(x,y,score){
        super(x,y)
        //通过super把X,Y的值传递给父对象,而super本身相当于调用父对象的构造函数
        //extends附赠了一个关键词super,super指向父类型的构造函数。调用super,就等效于调用父类型的构造函数了
        this.score = score;
      }
      show(){
        console.log(`敌军在(${this.x},${this.y})位置被击落,获得${this.score}分`)
      }
    }
    //奖励
    class Award extends Diren{
      constructor(x,y,award){
        super(x,y)//指向
        this.award=award;
      }
      show(){
        console.log(`在(${this.x},${this.y})的位置获得${this.award}的奖励`)
      }
    }
    // var dijun1 = new Diren(100,100)
    // dijun1.fly()
    //开始进行击落
    var jiluo = new Score(100,200,10)
    console.log(jiluo.show())
    //奖励得分
    var jiangli=new Award(200,200,"激光炮")
    jiangli.show()
    jiangli.fly()

promise

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值