初识ES6

 

    // 1、var 声明的变量是函数级作用域
    //       let和const是块级作用域。(在{}内声明的变量就只能在该区域内访问。)
        var age=18;
        if(age>18){
            var days=18*365;
            console.log(`虚度${days}天`);
        }
        days=2048;//由于var 是函数级作用域,所以在这里也能访问到。声明days的地方并不是在一个function当中。如果换成let或者const来访问,那么就会报错了。


        //如果使用var 在方法中声明变量,那么该变量只能在这个方法中使用。
        // 如果在函数外部声明,那么就可以当做全局变量来使用
        function GetPrice () {
             var price=100;//若是在该函数外使用price,则会报错undefined
             console.log(price);
        }
    //2、使用var声明的变量可以重复定义,而使用let或const声明的变量则不可以重复定义。
      var price=100;
      var price=200;//这里不会报错。
      const discount=0.9;
      let name="vichin";
      let name="stephen";//这里就会报错!
      if(discount>1){
          let name="stephen";//这里就不会报错。此前的name="vichin"是全局作用域,而此处的是块级作用域。
      }
      //当const类型的变量被赋值为一个值类型的值时,是不可以被重新赋值的。如果const类型的变量被赋值为一个引用类型的值时,是可以修改引用类型变量中的某些属性的。
      const person="vichin";
      person ="stephen";//这里就会报错。
      const person={
          name:'vichin';
          age:26
      };
      person.age=27;//这里就不会报错。
      // 如果不想让别人修改person对象中的属性,则可以使用
      const vichin=Object.freeze(person);

      // 当我们使用var关键字声明一个name的全局变量的时候,会产生环境污染,将window自带的属性name的值也给替换掉。往常的方法是使用一个立即执行函数,然后将变量声明在这个立即执行函数当中。
      // 可以使用let这个块级作用域的关键字来声明变量。
      {
          let name="vichin";
      }
变量声明

 

      //箭头函数(有点像lambda表达式)
      var fn=function(x){
          return x * x;//ES5中的语法
      }
      var fn2 = x => x * x;//ES6中的箭头函数。当只有一个参数传入的时候,可以省略小括号。去掉大括号,做到隐式返回。
      var fun= () => {//当没有参数传入的时候,一定要写小括号。
          return "vichin";
      }
      var fun2= (x,y) => {//当传递多个参数的时候,使用逗号间隔。
          return x * y;
      }
      const Jelly={
          name:"jelly",
          hobbies:['coding','sleeping','reading'],
          printHobbies:function(){
              this.hobbies.map(function(hobby){//这里的function是一个独立的函数,因此函数内的this并非指向Jelly这个对象,而是指向了Window。
                  console.log(`${this.name} love ${hobby}`);//严格模式下,这里会报错。
              })              
          },
          printLove:function(){
              this.love.map(hobby=>{
                  console.log(`${this.name} love ${hobby}`);//这里的this就指向了Jelly这个对象。
              })
          }
      }
      //不适合使用箭头函数的场景
      // 1、作为构造函数,一个方法需要绑定到对象
      const Person=(name,points)=>{//这里使用箭头函数,函数体中的this并不会指向即将生成的对象,而是指向了window
          this.name=name;
          this.points=points;
      }

        // 1、生成一个新的对象。
      // 2、将构造函数中的this指向新生成的对象。
      // 3、将这个对象绑定到它的原型对象中去。
      // 4、返回这个新生成的对象。
      const Jelly=new Person("jelly",5);
      Person.prototype.updatePoints=()=>{
          this.points++;//这里的this指向了父级作用域中的对象,window。
          console.log(this.points);
      }
      Person.prototype.updatePoints = function(argument){
           this.points++;//这里的this指向了父级作用域中的对象(Person)
          console.log(this.points);
      };
      //2、当你真的需要this的时候。
      const button=document.querySelector('.zoom');
      button.addEventListener('click', ()=>{//如果这里不用箭头函数,那么click的回调函数会与button对象进行绑定。
          this.classList.add('in');//由于使用了箭头函数,所以这里的this会是undefined。
          setTime(()=>{this.classList.remove('in');},2000)//此处的this仍然指向了button对象。如果使用了function,则this会指向window。(前面有提到过)
      })
      // 3、需要使用arguments对象
      const sum = () =>{
          return Array.from(arguments).reduce((prevSum,value) => prevSum + value,0)
      }
      //sum方法没有形参,所有arguments对象是不存在的。运行到Array.from(arguments)就会报错。
      // Array.from会将arguments对象转化成数组
箭头函数

 

      //函数中赋默认值
      function multiply (a = 5,b = 3) {
           return a * b;//以前是a=a||5
      }
函数中使用默认值

 

      //模板字符串
          const person ='vichin';
        const age=5;
        const sentence =`${person} is ${age*5} years old`;//在大括号中可以是一个变量,也可以是一个表达式或函数。
        console.log(sentence);
        const jelly={
            name:'jelly',
            date:'2018-11-09',
            todos:[
                {name:'Go to Store',complete:false},
                {name:'Watch Movie',complete:true},
                {name:'Running',complete:true},
            ]
        };
        function RenderTodos(todos){
            return (`<ul>
                ${todos.map(todo=>`
                    <li>
                        ${todo.name}${todo.complete?'√':'×'}
                    </li>
                `).join('')}
        </ul>`);
        }
        const template=`<div class='panel'>
        <div class='panel-header'>${jelly.name}</div>
        <div class='panel-body'>${RenderTodos(jelly.todos)}</div>
        <div class='panel-footer'>${jelly.date}</div>
        </div>`;//可以使用trim将空格去掉
模板字符串

 

        //标签模板字符串
        function HighLight(strings,...values){//...values剩余参数。
            //debugger;
            const highlighted=values.map(value=>`<span class='highlight'>${value}</span>`);
            let str='';
            strings.forEach((string, i) =>str +=`${string}${highlighted[i] || ''}`);
        }
        const user='vichin';
        const topic ='How to use the computer';
        const sentence =HighLight`${user} don't know ${topic}`;
模板标签字符串

 

        //对象结构
        const vichin={
            name:'vichin',
            age:25,
            family:{
                mother:'Max V',
                father:'Min V',
                brother:'V V'
            },
        }
        const {father,mother,brother}=vichin.family;//声明3个变量,并且使用family的3个属性为它们填充值。
        const {name:n,age,a,money='have no money'}=vichin;//为变量name和age重命名(防止此变量在之前被声明过)
对象解构

 

        //数组结构
        const numbers=['one','two','three','four'];
        const [one,two]=numbers;
        const [one,...others]=numbers;//会将数组中第一个数,放置在变量one中,其余的数会组成另一个数组。
        console.log(one,ohters)//one['tow','three','four']

        let a=10;
        let b=20;
        [a,b]=[b,a];//交换变量中的值
数组解构

 

        //For of loop(循环)可以用于数组,arguments对象,字符串,(nodeList)节点。
        const friuts=['Apple','Banana','Orange','Mango'];
        friuts.forEach( friut=> {
            console.log(friut);//在foreach中无法使用break和continue等关键字。
        });
        for(let i in friuts){        
            console.log(friuts[i]);
        }
        //使用for……in循环,会将friuts中的所有属性都枚举出来。单纯用在数组上还行。如果用在了对象上就不行了。
        //为了解决for……in的问题,可以使用for of 来解决这个问题。
        for(let friut of friuts){//在for of 循环中可以使用break和continue
            console.log(friut[0]);//打印索引
            console.log(friut[1]);//打印值
        }
        for(let [index,friut] of friuts.entries()){
            console.log(`${friut} ranks ${index+1} in my favorite friuts`);
        }
        let name='vichin';
        for (let char of name){
            console.log(char);//遍历字符串
        }
For of loop(循环)

 

        //Array.from和 Array.of
        //Array.from将一个类数组对象(有length属性的)或可遍历对象(继承Iterator接口)转换成一个数组
        const todos=document.querySelector('li');//获取界面上所有的li节点
        const names=Array.from(todos,todo=>todo.textContent);//先将todos转换成一个Array对象,再执行后面的一个lambda表达式。
        let name='vichin';
        Array.form(name);//将字符串转化为一个数组。

        let newAry=Array.of(1,2,3)//将1,2,3组成一个新的数组。

        //Array.find(element,index,array) Array.findIndex() Array.some() Array.every()
        const inventory=[
            {name:'apples',quantity:2},
            {name:'bananas',quantity:0},
            {name:'cherries',quantity:5}
        ];
        const bananas=inventory.find(friut =>friut.name==='bananas');//返回{name:'bananas',quantity:0}
        const bananasIndex=inventory.findIndex(friut => friut.name==='bananas');//返回1。
        const isEnough=inventory.some(friut => friut.quantity >0);//返回true。只要数组中有一个满足条件的就会返回true
        const isAllEnough=inventory.every(friut => friut.quantity>0);//返回false。在数组中,只要有一个不满足条件,就返回false。
Array对象新增的方法

 

        function sum(...numbers){//剩余参数。(将多个参数整合成一个数组)

        }
        function sum(arguments){

        }
        sum(1,2,3,4);
        function getCount(para1,...paras){

        }
剩余参数

 

        //spread operator intro 拓展运算符(将可遍历对象的每一个元素拓展为一个新的参数序列)
        const youngers=['George','John','Thomas']
        const olders=['James','Wade','Mike'];
        //要将两个组合成一个数组,以往的操作:
        let members=[];
        members=members.concat(youngers);
        members.push('Mary');
        members=members.concat(olders);

        //在ES6中可以使用拓展运算符来解决
        const  members=[...youngers,'Mary',...olders];
        const newAry=members;
        newAry[0]="vichin";//此时members中的第一个元素也会被改变。
        const newAry1=[...members];//可以解决这个问题。

        //拓展运算符的使用场景:
        //1、使用拓展运算发来替代Array.from()
        const todos=[...document.querySelectorAll('li')];//如果这里不用拓展运算符的话,那么就需要用Array.from()
        const names=todos.map(todo => todo.textContent);//这里方能使用todos.map方法。
        
        //2、使用现有数组,创建新的数组
        const  ary=['Georeg','John'];
        const name=['vichin',...ary];

        //3、删除数组中的某一项
        const todos=[
            {id:1,name:'Go to Store',completed:false},
            {id:2,name:'Watch TV',completed:true},
            {id:3,name:'Go Shopping',completed:false}    
        ];
        const id=2;
        const todoIndex= todos.findIndex(todo => todo.id === id);
        const newTodos=[...todos.slice(0,todoIndex),...todos.slice(todoIndex + 1)];//等到拼接后的新的数组,如果不加拓展运算符,那么新生成的newTodos变量只是一个对象的集合,而非数组
拓展运算符

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style type="text/css">
    
    .heading span{
        cursor: pointer;    
        display:inline-block;/*span是内联元素,内联元素无法实现该动画效果*/
        transition: transform 0.25;/*0.25秒的过渡时间*/
    }
    .heading span:hover{
        transform: translateY(-20px) rotate(10deg) scale(2);//Y轴移动-20px,旋转10度,放大2倍
    }
</style>
</head>
<body>
    <h2 class="heading">
        LARAVIST!
    </h2>
    <script type="text/javascript">
        const heading =document.querySelector('.heading');
        heading.innerHTML=wrapWithSpan(heading.textContent);
        function wrapWithSpan (word) {
            return [...word].map(letter => `<span>${letter}</span>`).join('');//使用join方法去掉逗号
        }
    </script>
</body>
</html>
拓展运算符实现动画效果

 

        //ES6中,对象字面量的改进。
        const name='vichn';
        const age=2;
        const birthday='2018-11';
        //以往的写法
        const person={
            name:name,
            age:age,
            birthday:birthday,
            greet(){//省略function关键字(方法简写)
                alert(`Hello ${this.name}`);
            }
        };
        //新的语法中(属性简写)
        const person={name,age,birthday};

        //计算属性
        let id=0;
        const userId={
            [`user-${++id}`]:id,//user-1:1,
            [`user-${++id}`]:id,//user-2:2,
            [`user-${++id}`]:id,//user-3:3,
        };        
        const values=['vichin',26,'2018-11-25'];
        const vichin={
            [keys.shift()]:values.shift(),
            [keys.shift()]:values.shift(),
            [keys.shift()]:values.shift(),
        };
对象字面量与属性

 

        //ES5中的原型继承
        function Person(name,age){//构造函数
            this.name=name;
            this.age=age;
        }
        //使用原型对象属性,新增原型对象方法。
        Person.prototype.method_name = function(argument){
             console.log(`Hi,I'm ${this.name}`); 
        };
        //实例化一个对象
        const vichin=new Person("vichin","27");
        //重写原型对象方法
        Person.prototype.method_name = function(argument){
             console.log(`Hi,I'm ${this.name},my age is ${this.age}`); 
        };
        //在成功的实例化一个对象之后,也可以继续为这个构造函数增加原型对象方法
        Person.prototype.method_name1 = function(argument){
             console.log("I'm a fan of James");  
        };
        //在ES6中,使用class来实现原型继承。(在JS中,类是一种特殊的函数)
        class Person{
            constructor(name,age){//类的构造函数
                this.name=name;
                this.age=age;
            }//这个地方没有逗号。
            info(){//定义一个方法
                console.log(`Hi,I'm ${this.name},my age is ${this.age}`); 
            }
            static Description(){
                console.log("I'm a fan of James");
            }
            //JS中的get,set
            set sex(value){
                this.sex=value;
            }
            get sex(){
                return `${this.sex}`;
            }
        }
        //使用关键字extends来继承父类Person
        class User extends Person{
            constructor(){
                super(name);//
                this.age;
            }
            eat(){//如果子类的方法名与父类的方法名是一样的,就会覆盖基类的方法。
                console.log('have dinner')
            }
        }
        const vichin=new User('vichin',27);
原型继承

 

//promise是一个对象,它能保存3种状态,pending,fulfilled和rejected。
    //pending表示一个异步的操作正在进行中。
    //fulfilled表示异步操作已经成功。
    //rejected表示异步操作失败。
    const promise = new Promise((resolve, reject) => { //创建一个promise对象
      //调用resolve可以将进行中的状态变成已成功。
      //reject可以将已成功的状态变成已失败。
      //一旦使用了resolve或reject,那么promise的状态就被固定住,不可更改了。
      //将要处理的异步代码写在promise的函数中。
      wx.getSystemInfo({
        success: (res) => { //在success中执行的代码表示已经执行成功。
          resolve(res); //将进行中状态改成已成功。
        },
        fail: (err) => {
          reject(err); //将状态改成已失败。
        }
      });
    });
    //可以随时的调用promise。来获取到异步调用的结果。
    //then方法内可以传递2个回调函数:
    //第一个回调函数表示当promise成功后要执行的函数。
    //第二个回调函数表示当promise失败后要执行的函数。
    promise.then(
      res => console.log(res), //箭头函数的简写
      err => console.log(err)
    );



//使用Promise来解决回调地狱的问题

    const hotList = bookModel.getHotList();//hotList是一个Promise对象
    hotList.then((res) => {//在第一次成功请求后台之后,再一次请求
      console.log(res);
      return bookModel.getMyBookCount();
    }).then((res)=>{//第三次请求后台API 
      console.log(res);
      return bookModel.getMyBookCount();
    })

    const detail = bookModel.getDetail(bid);//异步请求后台1
    const comments = bookModel.getComments(bid);//异步请求后台2
    const likeStatus = bookModel.getLikeStatus(bid);//异步请求后台3
    //Promise.all有点像C#中的Task.WhenAll方法,异步等待。(视频中说是将3个promise合并成一个promise,当3个promise方法完成后,就会执行合并后的promise中的then方法)。还有一个race(竞争)方法。
    Promise.all([detail,comments,likeStatus]).then(res=>{
      this.setData({
        book:res[0],
        comments:res[1].comments,
        like_status :res[2].like_status,
        likeCount:res[2].fav_nums
      });
        wx.hideLoading();
    });

 

posted @ 2018-12-09 09:08  水墨晨诗  阅读(264)  评论(0编辑  收藏  举报