JS高级-ES6语法汇总及案例练习

js方法文档

mdn

1.类和对象

类中属性和方法

  // 1.创建类class 创建一个明星类习惯定义首字母大写
    class Star {
      // 类的共有属性放到constructor里面
      constructor(uname, age) {
        this.uname = uname;
        this.age = age;
      }
      sing(song) {
        console.log(this.uname + '唱' + song);
      }
    }
    // 2.利用类创建对象new
    var ldh = new Star('刘德华', 21);
    ldh.sing('冰雨');
    console.log(ldh);
    // 类里面有个constructor函数,可以结束参数,同时返回实例对象
    // constructor函数只要new生成实例时,就会自动调用这个函数,如果我们不写,类也会自动生成这个函数
    // 类名后面不加小括号
  </script>

类的继承

可以继承类里面的属性和方法,就近原则

类里面的共有的属性和方法一定要加this使用

  • super继承属性
 class Father {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
      sum() {
        console.log(this.x + this.y);
      }
    }
    // 属性和方法都可以继承
    class Son extends Father {
      constructor(x, y) {
        //调用了父类中的构造函数,否则就传给子类会报错,因为用的是父类的this
        super(x, y);
      }
    }
    var son = new Son(2, 5);
    var son1 = new Son(11, 23);
    son.sum()
    son1.sum()
  </script>
  • super继承方法

    1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,有就执行子类

    2.如果子类没有,就去找父类,如果父类有,就执行父类的这个方法

       class Father {
          say() {
            return '天龙'
          }
        }
        class Son extends Father {
          say() {
            // console.log('八部');
            console.log(super.say() + '八部');//天龙八部
          }
        }
        var son = new Son();
    
  • 子类继承同时扩展自己

    class Father {
          constructor(x, y) {
            this.x = x;
            this.y = y;
          }
          sum() {
            console.log(this.x + this.y);
          }
        }
        // 属性和方法都可以继承
        class Son extends Father {
          constructor(x, y) {
            // 子类在构造函数中使用super必须放到this前面
            super(x, y);
            this.x = x;
            this.y = y;
          }
          subtract() {
            console.log(this.x - this.y);
          }
        }
        var son = new Son(9, 5);
        son.subtract();
        son.sum();
    

类的注意事项

   <button>点击</button>
    <script>
      var that;
      class Star {
        constructor(uname, age) {
          // constructor里面的this指向的是创建的实例对象
          // 类里面的共有属性和方法一定要加this使用
          that = this;
          this.uname = uname;
          this.age = age;
          // this.sing()
          this.btn = document.querySelector('button');
          // 不要加(),否则就直接调用了,
          this.btn.onclick = this.sing;
        }
        sing() {
          // 这里是btn调用,所以函数this是btn
          // console.log(this.uname);//undefined
          console.log(that.uname);
        }
      }
      var ldh = new Star('刘德华');
      // es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象

    </script>
  </body>

2.构造函数和原型

原型对象prototype

//每个构造函数都有一个prototype属性对象,这个对象的所有属性和方法都会被构造函数所有
 function Star(uname, age) {
      this.uname = uname;
      this.age = age;
      // this.sing=function(){
      //   console.log('我会唱歌');
      // }

      /* 原型是对象,prototype为原型对象
       方法为复杂数据类型会开辟新的内存空间
       原型的作用是共享方法,减少资源消耗*/
      Star.prototype.sing = function () {
        console.log('我会唱歌');
      }
    }
    var ldh = new Star('刘德华', 15);
    var zxy = new Star('张学友', 19);
    // 一般情况下,我们公共属性定义到构造函数里面,公共方法则定义到原型对象上
    console.log(ldh.sing === zxy.sing);//true

对象原型__proto__

<script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Star.prototype.sing = function () {
            console.log('我会唱歌');
        }
        var ldh = new Star('刘德华', 18);
        var zxy = new Star('张学友', 19);
        ldh.sing();
        console.log(ldh);//对象身上系统自己添加一个__proto__指向我们构造函数的原型对象prototype
        console.log(ldh.__proto__ === Star.prototype);//true
        // 方法的查找规则:首先看ldh 对象身上是否有sing方法,如果有就执行这个对象上的sing
        //如果没有sing这个方法,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法
    </script>

原型constructor

原型对象和对象原型都带ru有一个指向原来构造函数的constructor

function Star(uname, age) {
      this.uname = uname;
      this.age = age;
      // Star.prototype.sing = function () {
      //   console.log('我会唱歌');
      // },
      //   Star.prototype.movie = function () {
      //     console.log('我会演电影');
      //   }
    };
    // 很多情况下,我们需要手动的利用constructor这个属性指回原来的构造函数
    Star.prototype = {
       // 如果不加就指向一个对象了
      constructor: Star,
      sing: function () {
        console.log('我会唱歌');
      },
      movie: function () {
        console.log('我会演电影');
      }
    }

    var ldh = new Star('刘德华', 18);
    var zxy = new Star('张学友', 19);
    console.log(Star.prototype);
    console.log(ldh.__proto__);
    // 原型对象和对象原型都带有一个指向原来构造函数的constructor
    // console.log(Star.prototype.constructor);
    // console.log(ldh.__proto__.constructor);

原型链(就近原则)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6YXW5LC-1668090175085)(C:\Users\林威\Desktop\原型链简易版.jpg)]

原型链对象查找机制及this指向

  function Star(uname, age) {
      this.uname = uname;
      this.age = age;
      // 在构造函数中,里面this指向的是对象实例ldh
      console.log(this);
    }
    Star.prototype.sing = function () {
      console.log('我会唱歌');
      // 原型对象函数里面的this指向的也是实例对象ldh
      console.log(this);

    }
    var ldh = new Star('刘德华', 18);
    // 按原型链就近原则查找
    ldh.sex = '女';
    // Star.prototype.sex = '男';
    Object.prototype.sex = '男'
    console.log(ldh.sex);//女

call方法

call(),也可以调用函数,调用这个函数,并且修改函数运行时的this指向

  1. fun.call(thisArg,a1,a2)

  2. thisArg:当前调用函数this的指向对象

  3. a1,a2:传递的其他参数

  4. 借用父构造函数继承属性

     // 借用父构造函数继承属性
        function Father(uname, age) {
          this.uname = uname;
          this.age = age;
        }
        function Son(uname, age, score) {
          // this 指向子构造函数的对象实例
          Father.call(this, uname, age);
          this.score = score
        }
        var son = new Son('刘德华', 13, 99);
        console.log(son);
    

3.原型对象继承方法

 <script>
    function Father(uname, age) {
      this.uname = uname;
      this.age = age;
    };
    Father.prototype.money = function () {
      console.log('我要赚钱');
    }
    function Son(uname, age) {
      Father.call(this, uname, age)
    }
    // Son.prototype=Father.prototype这样有问题,如果修改了子原型对象,父原型对象会跟着要求变化

    Son.prototype = new Father();
    Son.prototype.constructor = Son;
    Son.prototype.exam = function () {
      console.log('孩子要考试');
    }
    var son = new Son('dad', 45);
    console.log(son);
    console.log(Father.prototype);
  </script>

4.ES5新增数组方法

文档

3个参数(当前项的值,当前的索引,数组对象本身)

forEach遍历

<script>
    var arr = [1, 2, 3];
    var sum = 0;
    arr.forEach(function (a, b, c) {
      console.log('数组元素' + a);
      console.log('数组索引号' + b);
      console.log('数组本身' + c);
      sum += a;
    })
    console.log(sum);//6

filter筛选

 // ilter筛选数组,返回一个新的数组1
    var arr = [12, 33, 44, 66, 3, 7]
    var newArr = arr.filter(function (value, index, total) {
      // return value % 2 === 0;
      return value >= 20
    })
    console.log(newArr);
  </script>

some✴️

检测数组中的元素是否满足指定条件,返回的是布尔值,如果查到就返回true,否则false

如果找到第一个满足条件的元素,则终止循环,不在继续查找;

要终止循环return后面一定要加turn

 var arr = [10, 24, 4];
    var flag = arr.some(function (value) {
      return value > 20
    })
    console.log(flag);//true

    var arr1 = ['red', 'pink', 'green'];
    var flag1 = arr1.some(function (value) {
      return value === 'pink';
    })
    console.log(flag1);//true

find

方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefinedvar ary = [{
			id: 1,
			name: '张三'
		}, {
			id: 2,
			name: '李四'
		}];
		// 如果查找不到就返回undefind
		let target = ary.find(item => item.id===2);
		console.log(target)

findIndex

	let ary = [10, 20, 50];
		// 用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
		let index = ary.findIndex(item => item > 15);
		console.log(index);//1

includes

includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false

const array1 = [1, 2, 3];

console.log(array1.includes(2));
// expected output: true

const pets = ['cat', 'dog', 'bat'];

console.log(pets.includes('cat'));
// expected output: true

console.log(pets.includes('at'));
// expected output: false

flat

看上面文档

flatmap

reduce

计算数组所有元素的总和

// 	注意:如果设置初始值,那么在第一次调用回调函数时,prev的值为这个初始值,如果不设置初始值,那么默认情况下,prev的值为数组的第一个元素
        var a = [1, 2, 3]
        var b = a.reduce(function (h, f) {
            return h + f
        }, 5)//5+1+2+3
        console.log(b);//11
------------------------------------------------
//返回未被选中的    
    undoneLength() {
    return state.list.reduce((pre, item) => {
      return pre + (item.done === true ? 0 : 1)
    }, 0)
  },

join

数组转为字符串

5.字符串方法

trim

trim(),去除字符串两侧空格,返回一个新的字符串

 var str = '  an  dy  ';
    console.log(str);
    var str1 = str.trim();
    console.log(str1);

startsWith()和endsWith()

  1. startsWith():表示参数字符串是否在字符串的头部,返回布尔值

  2. endsWith():表示参数字符串是否在字符串的尾部,返回布尔值

    let str = 'Hellow word';
        str = str.startsWith('He');
        console.log(str);
    

repeat

	// repeat方法表示将原字符串重复n次,返回一个新字符串
		console.log("y".repeat(5))

split

字符串转为数组

6.Object.defineProperty()

object.defineProperty(obj,prop,descriptor)

只有用这个方法加进去的才受控制

  • obj:必需。目标对象

  • prop:必需。需定义或修改的属性的名字

  • descriptor:必需。目标属性所拥有的特性

    • value:设置属性的值
    • writable:值是否可以重写修改。true/false,默认为false
    • enumerable:目标属性是否可以被枚举。true/false,默认为false
    • configurable:目标属性是否可以被删除或是否可以再次修改特性true/false,默认为false
    • 这里id是本身有的,所以不受控制
      var obj = {
          id: 1,
          pname: '小米',
          price: 1999
        };
        // 有则修改,无则添加
        Object.defineProperty(obj, 'num', {
          value: 1000,
          // 因为writable默认为false
        });
        obj.num = 3;
        obj.id = 3;
        console.log(obj);//id:3,num:1000
    

7.函数

函数定义方式

   // 函数的定义方式
        // 1.自定义函数(命名函数)
        function fn() { }
        // 2.函数表达式(匿名函数)
        var fun = function () { };
        // 3.利用 new Function('参数1','参数2','函数3');
        // 了解就好,效率较低
        var f = new Function('a', 'b', 'console.log(a+b)');
        f(1, 2);
        // 4.所有函数都是 Function 的实例(对象)
        console.dir(f);
        // 5.函数也属于对象
        console.log(f instanceof Object);

this指向

调用方式this指向
普通函数调用window
构造函数调用实例对象,原型对象里面的方法也指向实例对象
对象方法调用该方法所属对象
事件绑定方法绑定事件对象
定时器函数window
立即执行函数window

apply方法

    //   改变函数内this指向 js 提供了3种方法 call() apply() bind()
        // 2.apply() 应用 运用的意思
        var o = {
            name: 'andy'
        };
        function fn(arr) {
            console.log(this);
            console.log(arr);//'red'
        };
        fn.apply(o, ['red']);
        // 1.也是调用函数 第2跟可以改变函数内部的this指向
        // 2.但是他的参数必须是数组,也可以是伪数组
        // 3.apply 的主要应用 比如说我们可以利用 apply  借助于数学内置对象求最大值
        // Math.max()
        var arr = [1, 66, 3, 99, 4];
        var max = Math.max.apply(Math, arr);
        var min = Math.min.apply(Math, arr);
        console.log(max,min);

bind方法⭐️

 var o = {
      name: 'andy',
    }
    function fn(a, b) {
      console.log(a + b);
      console.log(this);
    }
    // 改变this的同时不会直接调用,而是返回一个新的函数
    var f = fn.bind(o, 2, 4);
    f();

应用场景函数内部的this指向

都可以改变

  1. call经常做继承·

  2. apply经常和数组有关系,比如借助数组对象实现最大值最小值

  3. bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向

    var btns = document.querySelectorAll('button');
            for (var i = 0; i < btns.length; i++) {
                btns[i].onclick = function () {
                    this.disabled = true;
                    setTimeout(function () {
                        this.disabled = false;
                    }.bind(this), 2000)//bind写在定时器函数的外面,this指向btn这个对象
                }
            }
    

高阶函数

是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出

  function fn(a, b, callback) {
            console.log(a + b);
            callback && callback();
        }
        fn(1, 2, function() {
            console.log('我是最后调用的');

        });

8.闭包

一个作用域可以访问另外一个函数内部的局部变量,是延申了变量的作用范围

// 闭包(closure) 指有权访问另一个函数作用域中变量的函数
    // 简单理解:一个作用域可以访问另外一个函数内部的局部变量
    // 闭包:我们fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量num
    /*function fn() {
      var num = 5;
      function fun() {
        console.log(num);
      }
      fun()
    }
    fn()
    */
    // 利用闭包,我们外面的作用域可以访问fn内部的局部变量
    //就是延申了变量的作用范围
    function fn() {
      var num = 10;
      // function fun() {
      //   console.log(num);
      // };
      // return fun;
      return function () {
        console.log(num);
      }
    }
    var f = fn();
    f();

9.递归

函数内部自己调用自己

  /*
    var num = 1;
    function fn() {
      console.log('打印6句话');
      if (num == 6) {
        return;//
      }
      num++;
      fn();
    }
    fn();
    */
    // 利用递归求1~n的阶乘
    function fn(n) {
      if (n == 1) {
        return 1
      }
      return n * fn(n - 1)
    }
    console.log(fn(3));
  </script>

利用递归遍历数据

 //  输入id,就可以返回对应的数据对象
    var data = [{
      id: 1,
      name: '家电',
      goods: [{
        id: 11,
        gname: '冰箱',
        goods: [{
          id: 111,
          gname: '海尔'
        }, {
          id: 112,
          gname: '美的'
        },]
      }, {
        id: 12,
        gname: '洗衣机'
      }]
    }, {
      id: 2,
      name: '服饰'
    }];
    function select(json, id) {
      var o = {};
      json.forEach(function (value) {
        if (value.id == id) {
          o = value;
        } else if (value.goods && value.goods.length > 0) {
          o = select(value.goods, id)
        }
      })
      return o;
    }
    console.log(select(data, 111));

10.拷贝

浅拷贝

浅拷贝对于更深层次对象级别只拷贝引用,所以改值对两个对象都有影响

  var obj = {
      id: 1,
      name: 'andy',
      msg: {
        age: 17,
      }
    };
    var o = {};
    for (var i in obj) {
      // k是属性名,obj[k]属性值
      o[i] = obj[i];
    }
    // 
    o.msg.age = 12;
    // 浅拷贝对于更深层次对象级别只拷贝引用,所以改值对两个对象都有影响
    console.log(obj);
    console.log(o);
------------------------------------------
    ES6浅拷贝语法糖Object.assign()
Object.assign(o,obj);//把obj拷贝给o
  console.log(o);

深拷贝

修改源对象更深层次对象不会影响拷贝的对象的值,互不影响

 var obj = {
      id: 1,
      name: 'andy',
      msg: {
        age: 18
      },
      color: ['pink', 'red']
    };
    var o = {};
    function deepCopy(newObj, oldObj) {
      for (var i in oldObj) {
        var item = oldObj[i];
        if (item instanceof Array) {
          newObj[i] = [];
          deepCopy(newObj[i], item)
        } else if (item instanceof Object) {
          newObj[i] = {};
          deepCopy(newObj[i], item)
        } else {
          newObj[i] = item;
        }
      }
    }
    deepCopy(o, obj);
    console.log(o);
    console.log(obj);
    obj.msg.age = 1;
    console.log(o);

11.正则表达式

菜鸟正则

正则在js中的创建使用

 // 方法1.利用RegExp对象来创建正则表达式
    var regexp = new RegExp(/123/);
    console.log(typeof regexp);
    console.log(regexp);
    //2.利用字面量创建正则表达式
    var rg = /123/;
    // 3.test方法用来检测字符串是否符号正则表达式要求的规范
    console.log(rg.test(123));//true
    console.log(rg.test('abc'));//false
    console.log(regexp.test(1234));//true

边界符的使用

//正则表达式里面不需要加引号 不管是数字还是字符型

 // 边界符^ $
    var rg = /abc/;//正则表达式里面不需要加引号 不管是数字还是字符型
    //   /abc/ 只要包含有abc这个字符串返回的都是true
    console.log(rg.test('abc'));
    console.log(rg.test('abcd'));
    console.log(rg.test('aabcd'));
    console.log('--------------');
    var reg = /^abc/;  //必须以abc开头
    console.log(reg.test('abc'));
    console.log(reg.test('abcd'));
    console.log(reg.test('aabcd'));//false
    console.log('--------------');
    var reg = /abc$/;  //必须以abc结尾
    console.log(reg.test('abc'));
    console.log(reg.test('abcd'));//false
    console.log(reg.test('dabc'));
    console.log('--------------');
    var reg = /^abc$/;  //精确匹配,要求必须是abc 字符串才符合规范
    console.log(reg.test('abc'));
    console.log(reg.test('abcd'));//false
    console.log(reg.test('aabcd'));//false
    console.log(reg.test('abcabc'));//false

字符类

// 字符类: [] 表示有一系列字符可供选择,只要1匹配其中一个就可以了

    //   var rg=/abc/; 只要包含abc就可以
        // 字符类: [] 表示有一系列字符可供选择,只要1匹配其中一个就可以了
        var rg = /[abc]/;  //只要包含有a 或者包含有b 或者包含有C 都返回为true
        console.log(rg.test('andy'));
        console.log(rg.test('baby'));
        console.log(rg.test('color'));
        console.log(rg.test('red'));//false
        console.log('------------------');
        var rg1 = /^[abc]/;  //只要其中任何一个开头都可以
        console.log(rg1.test('aa'));
        console.log(rg1.test('a'));
        console.log(rg1.test('b'));
        console.log(rg1.test('c'));
        console.log(rg1.test('dabc'));//false
        console.log('------------------');
        var rg1 = /^[abc]$/;  //3选1 只有是a 或者是b 或者是c 这3个字母才返回true
        console.log(rg1.test('aa'));//false
        console.log(rg1.test('a'));
        console.log(rg1.test('b'));
        console.log(rg1.test('c'));
        console.log(rg1.test('abc'));//false
        console.log('------------------');
        var rg1 = /^[a-z]$/;   //26个英文字母任何一个字母返回的都是true -表示a到z的范围
        console.log(rg1.test('g'));
        console.log(rg1.test('A'));//false
        console.log(rg1.test('z'));
        console.log(rg1.test(1));//false
        console.log('------------------');
        // 字符组合
        var rg1 = /^[a-zA-Z0-9_-]$/;   //26个英文字母(大小写)任何一个字母返回的都是true -表示范围
        console.log(rg1.test('a'));
        console.log(rg1.test('B'));
        console.log(rg1.test('8'));
        console.log(rg1.test('_'));
        console.log(rg1.test('-'));
        console.log(rg1.test('!'));//false
        console.log('------------------');
        // 如果中括号里面有^ 表示取反的意思 千万和我们边界符^ 别混淆
        var rg1 = /^[^a-zA-Z0-9_-]$/;   //26个英文字母(大小写)任何一个字母返回的都是true -表示范围
        console.log(rg1.test('a'));
        console.log(rg1.test('B'));
        console.log(rg1.test('8'));
        console.log(rg1.test('_'));
        console.log(rg1.test('-'));
        console.log(rg1.test('!'));//true

量词

   // 量词符: 用来设定某个模式出现的次数
        // 简单理解: 就是让下面的a这个字符重复多少次
        // var reg = /^a$/;
        //  * 相当于 >= 0 可以出现0次或者很多次 
        var reg = /^a*$/;
        console.log(reg.test(''));
        console.log(reg.test('a'));
        console.log(reg.test('aaa'));

        //  + 相当于 >= 1 可以出现1次或者很多次
        // var reg = /^a+$/;
        // console.log(reg.test('')); // false
        // console.log(reg.test('a')); // true
        // console.log(reg.test('aaaa')); // true

        //  ?  相当于 1 || 0
        // var reg = /^a?$/;
        // console.log(reg.test('')); // true
        // console.log(reg.test('a')); // true
        // console.log(reg.test('aaaa')); // false

        //  {3 } 就是重复3次
        // var reg = /^a{3}$/;
        // console.log(reg.test('')); // false
        // console.log(reg.test('a')); // false
        // console.log(reg.test('aaaa')); // false
        // console.log(reg.test('aaa')); // true
        //  {3, }  大于等于3
        var reg = /^a{3,}$/;
        console.log(reg.test('')); // false
        console.log(reg.test('a')); // false
        console.log(reg.test('aaaa')); // true
        console.log(reg.test('aaa')); // true
        //  {3,16}  大于等于3 并且 小于等于16
        var reg = /^a{3,6}$/;
        console.log(reg.test('')); // false
        console.log(reg.test('a')); // false
        console.log(reg.test('aaaa')); // true
        console.log(reg.test('aaa')); // true
        console.log(reg.test('aaaaaaa')); // false
    </script>

括号

  // 中括号 字符集合 匹配方括号中的任意字符
        var reg = /^[abc]$/;
        // a 也可以 b也可以 c 可以 a||b||c
        // 大括号 量词符 里面表示重复次数
        var reg=/^abc{3}$/;   //它只是让c重复3次  abccc
        console.log(reg.test('abc'));
        console.log(reg.test('abcabcabc'));
        console.log(reg.test('abaccc'));
        console.log(reg.test('abccc'));//true
        // 小括号 表示优先级
        var reg=/^(abc){3}$/;   //它只是让abc重复3次  abcabcabc
        console.log(reg.test('abc'));
        console.log(reg.test('abcabcabc'));//true
        console.log(reg.test('abaccc'));
        console.log(reg.test('abccc'));

替换

  // 替换 replace
        // var str = 'andy和red';
        // // var str1=str.replace('andy','baby');
        // var str1=str.replace(/andy/,'baby');
        // console.log(str1);
        var text=document.querySelector('textarea');
        var btn=document.querySelector('button');
        var div=document.querySelector('div');
        btn.onclick=function(){
            // g:全局匹配 i:忽略大小写  gi:全局匹配+忽略大小写
            div.innerHTML=text.value.replace(/激情|gay/g,'**');
        }

12.阮一峰ES6

Es6文档

12.let和const关键字

let关键字声明变量

  1. let声明的变量只在所处于的块级作用域有效

  2. 块级作用域: 全局,函数

    if(true){
        let a=10
    }
    console.log(a);// a is not defined
    
  3. 不存在变量提升

     console.log(a);
        let a = 100;
    
  4. 存在暂时性死区

    var tmp = 123;
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    

let经典面试题

  var arr = [];
    for (var i = 0; i < 2; i++) {
      arr[i] = function () {
        // 函数内部没有定义i的代码,所以会按原型链往上查找
        console.log(i);
      }
    }
    arr[0]();//2
    arr[1]();//2
    // 因为i是全局变量,函数调用的时候for早就执行完了

    var arr1 = [];
    //let有块级作用域
    for (let i = 0; i < 2; i++) {
      arr1[i] = function () {
        console.log(i);
      }
    }
    arr1[0]();//0
    arr1[1]();//1

const声明常量⭐️

  • const声明的常量只在所处于的块级作用域有效

  • 使用const关键字声明的常量必须赋初始值

  • 常量赋值后不能更改两种情况

        // 常量赋值后,值不能修改
        // const a = 3;
        // a = 4;
        // 但是复杂数据类型可以这样
        const arr = [1, 2];
        arr[0] = '上';
        arr[1] = '下';
        console.log(arr);//['上','下']
        arr = ['a', 'n']//报错,不能这样改值,这样更改了内存地址
    
  • varletconst
    函数级作用域块级作用域块级作用域
    变量提升不存在变量提升不存在变量提升
    值可更改值可更改值不可更改

作用域

 <button>1</button>
  <button>2</button>
  <button>3</button>
  <script>
    var btns = document.querySelectorAll('button');
    // for (var i = 0; i < btns.length; i++) {
    //   btns[i].addEventListener('click', function () {
    //     console.log(i);//3
    //   })
    // }
    // 解决方法1
    // for (let i = 0; i < btns.length; i++) {
    //   btns[i].addEventListener('click', function () {
    //     console.log(i);//3
    //   })
    // }
    // 解决方法2
    for (let i = 0; i < btns.length; i++) {
      (function (i) {
        btns[i].addEventListener('click', function () {
          console.log(i);
        })
      })(i)
    }
  </script>

对象字面量增强写法

<script>
    // 属性的增强写法
    const name = 'why';
    const age = 16;
    const height = 188;
    /*Es5写法
      const obj = {
        name: name,
        age: age,
        height: height
      }
      */
    const obj = {
      name,
      age,
      height
    }
    console.log(obj);
    // 函数方法的简写
    //Es5的写法
    let obj1 = {
      test: function () {
        console.log(777);
      },
      test() {
        console.log('我是简写');
      }
    }
  </script>

13.解构赋值

从数组和对象中提取值,对变量进行赋值,这被称为解构,j建议直接看文档

数组解构

let ary = [1, 2, 3];
    // 多出来的解构失败,显示undefined
    let [a, b, c, d] = ary;
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);//undefined

对象解构

使用变量的名字匹配对象的属性,匹配成功将对象属性的值赋值给变量

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

     let { bar, foo } = { foo: 'c', bar: 'a' }
        console.log(bar);//a
        console.log(foo);//c
    
     //对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
        let { bar, foo } = { foo: 'c', bar: 'a' }
        console.log(bar);//a
        console.log(foo);//c
        let { baz } = { hd: 'aaa', gr: 'bbb' };
        console.log(baz);//undefineds
    
  • 如果变量与属性名不一样,还想要匹配成功则需要设置别名,利用别名解构

   let { n: bm } = { a: 'c', g: 'k', n: 5 };
      console.log(bm);//5

14.箭头函数

菜鸟箭头文档

箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调

箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法

  • 语法表达

      const fn = () => {
          console.log(123);
        }
        fn();//123
    
  • // 如果函数体只有一句代码,且代码的执行结果就是返回值,可以省略大括号

    const sum = (n1, n2) => n1 + n2;
      var result = sum(3, 5);
      console.log(result);//8
  • 如果形参只有一个,可以省略小括号

     const single = v => {
          alert(v);
        }
        single(20)
    

    // 箭头函数不绑定this 箭头函数没有自己的this关键字 如果在箭头函数中使用this关键字将指向箭头函数定义位置中的this

    ​ // 局部作用域(函数作用域)

    function fn() {
          console.log(this);
          return () => {
            console.log(this)
          }
        }
        const obj = { name: 'zhangsan' };
    
        const resFn = fn.call(obj);
        resFn();
    
  • 对象是不能产生作用域的

    	var age = 100;
    
    		var obj = {
    			age: 20,
    			say: () => {
    				console.log(this.age);//100
    			},
    			s: function () {
    				console.log(this.age);//20
    			}
    		}
    		// 对象是不能产生作用域的
    		obj.say();
    		obj.s()
    

15.剩余参数

剩余参数是将剩余的元素放在一个数组中

 // 剩余参数是将剩余的元素放在一个数组中
    const sum = (...args) => {
      var total = 0;
      args.forEach(item => {
        total += item;
      })
      return total;
    }
    console.log(sum(12, 34));

    // 剩余参数+数组解构
    let ary1 = ['张三', '李四', '王五'];
    let [s1, ...s2] = ary1;//s2变成了一个数组
    console.log(s1)
    console.log(s2)

16.扩展运算符

扩展运算符可以将数组或者对象转为用逗号分隔的参数序列

 // 扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
    let arr = ['a', 'b', 'c'];
    // 这里没逗号是因为被当成了log方法的分隔符
    console.log(...arr);//1 2 3

    // 扩展运算符应用于数组合并
    let arr1 = [1, 2, 3];
    let arr2 = [4, 5, 6];
    let arr3 = [...arr1, ...arr2];
    console.log(arr3);
    //方法2
    arr3.push(...arr1);
    console.log(arr3);

利用扩展运算符将伪数组转换为真正的数组

	var oDivs = document.getElementsByTagName('div');
		console.log(oDivs);//实际上就是伪数组
		var ary = [...oDivs];//数组
		// 变成数组后就可以运用数组方法了
		ary.push('a');
		console.log(ary);

17.Array.form

1.将伪数组或可遍历对象转换为真正的数组

2.第2个参数为回调函数,

   var arrayLike = {
      '0': 1,
      '1': 2,
      '2': 3,
      length: '3'
    }
    console.log(arrayLike);
    // var newArr = Array.from(arrayLike);
    //console.log(newArr);//[1,2,3];
    //  第2个参数为回调函数
    var newArr = Array.from(arrayLike, item => item * 2);
    console.log(newArr);//[2,4,6]

18.模板字符串

 // es6新增的创建字符串的方式,使用反引号定义
        // let name=`这是一个模板字符串`;
        // let a=`张飞`;
        // console.log(`我的兄弟是${a}`);
        // console.log(name);

        // let result={
        //     name:'张三',
        //     age:20
        // };
        // let html=`
        // <div>
        //     <span>${result.name}</span>
        //     <span>${result.age}</span>
        // </div>
        // `;
        // console.log(html);
        const fn = function () {
            return '关羽';
        }
        let b = `你是${fn()}`;
        console.log(b);
        console.log(`付电费,
        放到`);

19.Set,Map方法⭐️

类似于数组,但成员的值都是唯一的,没有重复的值

// es6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值
    // Set本身是一个构造函数,用来生成Set数据结构
    // const s1 = new Set();
    // // size 表示此数据结构中包含多少值
    // console.log(s1.size)
    // // Set函数可以接收一个数组作为参数,用来初始化
    // const s2 = new Set(["a", "b"]);
    // console.log(s2.size)
    // // 可以做到数组去重
    // const s3 = new Set(["a", "a", "b", "b"]);
    // console.log(s3.size);//2 具有去重功能
    // console.log(s3)
    // const ary = [...s3];
    // console.log(ary)
    const s4 = new Set();
    // 向set结构中添加值 使用add方法 返回结构本身
    s4.add('a').add('b');
    console.log(s4.size);//2

    // 从set结构中删除值 用到的方法是delete 返回布尔值
    const r1 = s4.delete('c');
    console.log(s4.size)
    console.log(r1);

    // 判断某一个值是否是set数据结构中的成员 使用has 返回布尔值
    const r2 = s4.has('d');
    console.log(r2)

    // // 清空set数据结构中的值 使用clear方法
    // s4.clear();
    // console.log(s4.size);

    // 遍历set数据结构 从中取值
    const s5 = new Set(['a', 'b', 'c']);
    s5.forEach(value => {
      console.log(value)
    })

20.Es6模块化

Es6文档

1.想要在nodejs中体验es6模块化
在package.json里面加入“type":‘module’

{
  "type": "module",
  "name": "code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "then-fs": "^2.0.0"
  }
}

2.默认导入和导出

默认导出
let n1 = 10
let n2 = 20
function show() {}

export default {
  n1,
  show
}
默认导入不要加{}
import m1 from './01.默认导出.js'

console.log(m1)
每个模块中,只允许使用唯一的一次export default

3.按需导入和导出

按需导出
export let s1 = 'aaa'
export let s2 = 'ccc'
export function say() {}
按需导入要加{}
取别名,这里给s2取了别名
import { s1, s2 as str2, say } from './03.按需导出.js'

console.log(s1)
console.log(str2)
console.log(say)

4.默认与按需导入导出写一块

export let s1 = 'aaa'
export let s2 = 'ccc'
export function say() {}

export default {
  a: 20
}
导入
import info, { s1, s2 as str2, say } from './03.按需导出.js'

console.log(s1)
console.log(str2)
console.log(say)

console.log(info)

运行结果
aaa
ccc
[Function: say]
{ a: 20 }    

5.直接运行模块中的代码

导出
for (let i = 0; i < 3; i++) {
  console.log(i)
}

导入
import './05.直接运行模块中的代码.js'

运行结果
0
1
2

21.Promise

Es6文档

  • 基本语法
 const p = new Promise(function (resolve, reject) {
      let date = '你是奔达嘛';
      // resolve(date);
      reject(date);//对应第then的第2个状态
    }).then(function (value) {
      console.log(value);
    }, function (reason) {
      console.error(reason);
    })
  • catch

     const p = new Promise((resolve, reject) => {
          setTimeout(() => {
            //设置 p 对象的状态为失败, 并设置失败的值
            reject("出错啦!");
          }, 1000)
        });
    
        // p.then(function(value){}, function(reason){
        //     console.error(reason);
        // });
    
        p.catch(function (reason) {
          console.warn(reason);
        });
    
  • 读取文件

    // 1.引入fs模块
    const fs = require('fs')
    // 2.调用方法读取文件
    //3. 使用 Promise 封装
    const p = new Promise(function (resolve, reject) {
      fs.readFile('./resources/为学.md', (err, data) => {
        if (err) reject(err);
        resolve(data)
      });
    }).then(value => {
      return new Promise(function (resolve, reject) {
        fs.readFile('./resources/插秧诗.md', (err, data) => {
          if (err) reject(err);
          resolve([value, data])
        });
      })
    }).then(value => {
      return new Promise(function (resolve, reject) {
        fs.readFile('./resources/观书有感.md', (err, data) => {
          if (err) {
            reject(err)
          } else {
            value.push(data);
            resolve(value)
          }
        })
      })
    }).then(value => {
      console.log(value.toString());
    })
    // p.then(function (value) {
    //   console.log(value.toString());
    // }, function (item) {
    //   console.log('读取失败');
    // })
    

promise.all

Promise.all([
      // new Promise((resolve, reject) => {
      //   $.ajax({
      //     url: 'url1',
      //     success: function (data) {
      //       resolve(data)
      //     }
      //   })
      // }),
      // new Promise((resolve, reject) => {
      //   $.ajax({
      //     url: 'url2',
      //     success: function (data) {
      //       resolve(data)
      //     }
      //   })
      // })

    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({name: 'why', age: 18})
      }, 2000)
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({name: 'kobe', age: 19})
      }, 1000)
    })
  ]).then(results => {
    console.log(results);

22.async和await

async

 // 只要返回的结果表示promise对象,返回的结果就是成功的Promise对象
    async function fn() {
      // async函数的返回值是 Promise 对象
      // return '绝世武神'
      //return; //undefined
      //返回的结果是一个失败的promise
      //throw new Error('出错啦!')
      //返回的结果是一个Promise对象
      return new Promise((resolve, reject) => {
        //  resolve('成功的数据')对应then的第1个参数
        reject('失败的数据');//对应then的第2个参数
      })
    }
    const hs = fn();
    console.log(hs);
    hs.then(success => {
      console.log(success);
    }, error => {
      console.log(error);
    })

await

 const p = new Promise(function (resolve, reject) {
      //resolve('成功的值');
      reject('失败的值')
    })
    // await要放在async函数中
    /* async function main() {
       // await返回的结果就是promise对象成功的那个值
       let result = await p;
       console.log(result);
     }*/

    /*任何一个await语句后面的 Promise 对象变为reject状态,
    那么整个async函数都会中断执行。
    我们希望即使前一个异步操作失败,也不要中断后面的异步操作。
    这时可以将第一个await放在try...catch结构里面,
    这样不管这个异步操作是否成功,第二个await都会执行。*/
    async function main() {

      try {
        let result = await p;
        console.log(result);
      } catch (e) {
        console.log(e);//失败的值
      }
    }
    main()

在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行

const fs = require('fs');
function readWx() {
  return new Promise(function (resolve, reject) {
    fs.readFile('./resources/为学.md', (err, data) => {
      if (err) reject(err);
      resolve(data)
    });
  })
};
function readCys() {
  return new Promise(function (resolve, reject) {
    fs.readFile('./resources/插秧诗.md', (err, data) => {
      if (err) reject(err);
      resolve(data)
    });
  })
};
function readGsyg() {
  return new Promise(function (resolve, reject) {
    fs.readFile('./resources/观书有感.md', (err, data) => {
      if (err) reject(err);
      resolve(data)
    });
  })
}
console.log('A');

async function main() {
  console.log('B');
  let Wx = await readWx();
  let Cys = await readCys();
  let Gsyg = await readGsyg();
  console.log(Wx.toString());
  console.log(Cys.toString());
  console.log(Gsyg.toString());
  console.log('C');
}
main();
console.log('D');
// 在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行
//ABD....C
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值