zoukankan      html  css  js  c++  java
  • 最常用的ES6特性

    遇到了要写出es6新特性的题目,所以查阅了资料来总结一下,点击查看原文

    进入正题,最常用的ES6特性有:let, const, class, extends, super, arrow functions, template string, destructuring, default, rest arguments。

    1.let,const

    针对目标:块级作用域

    关于这两个特性,可以先查看我的博客:js中const,var,let区别

    在之前的基础上,进行补充:ES5只有全局作用域和函数作用域,没有块级作用域,这让var带来很多不合理的场景,比如下面的例子——用来计数的循环变量泄露为全局变量。

    1 var a = [];
    2 for (var i = 0; i < 10; i++) {
    3   a[i] = function () {
    4     console.log(i);
    5   };
    6 }
    7 a[6](); // 10

    上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。而使用let则不会出现这个问题。

    1 var a = [];
    2 for (let i = 0; i < 10; i++) {
    3   a[i] = function () {
    4     console.log(i);
    5   };
    6 }
    7 a[6](); // 6

    再来一个例子(使用了闭包):预期结果是点击不同的clickBox,显示不同的 i

    1 var clickBoxs = document.querySelectorAll('.clickBox')
    2 for (var i = 0; i < clickBoxs.length; i++){
    3     clickBoxs[i].onclick = function(){
    4         console.log(i);//事实是无论我们点击哪个clickBox,输出的都是5
    5     }
    6 }

    所以我们用闭包搞定它

     1 function iteratorFactory(i){
     2     var onclick = function(e){
     3         console.log(i);
     4     }
     5     return onclick;
     6 }
     7 var clickBoxs = document.querySelectorAll('.clickBox');
     8 for (var i = 0; i < clickBoxs.length; i++){
     9     clickBoxs[i].onclick = iteratorFactory(i);
    10 }

    2.class, extends, super

    针对目标:原型、构造函数,继承

     1 class Animal {
     2     constructor(){
     3         this.type = 'animal';
     4     }
     5     says(say){
     6         console.log(this.type + ' says ' + say);
     7     }
     8 }
     9 
    10 let animal = new Animal();
    11 animal.says('hello'); //animal says hello
    12 
    13 class Cat extends Animal {
    14     constructor(){
    15         super();
    16         this.type = 'cat';
    17     }
    18 }
    19 
    20 let cat = new Cat();
    21 cat.says('hello');//cat says hello

    上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实例对象可以共享的。

    Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。上面定义了一个Cat类,该类通过extends关键字,继承了Animal类的所有属性和方法。

    super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

    ES6的继承机制,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。

    P.S 如果你写react的话,就会发现以上三个东西在最新版React中出现得很多。创建的每个component都是一个继承React.Component的类。

    3.箭头函数

    针对目标:函数简洁,this问题

    1 //传统写法
    2 function(x, y) { 
    3     x++;
    4     y--;
    5     return x + y;
    6 }
    7 //ES6箭头函数写法
    8 (x, y) => {x++; y--; return x+y}

    传统写法会出现的this问题:

     1 class Animal {
     2     constructor(){
     3         this.type = 'animal';
     4     }
     5     says(say){
     6         setTimeout(function(){
     7             console.log(this.type + ' says ' + say);
     8         }, 1000);
     9     }
    10 }
    11 
    12  var animal = new Animal();
    13  animal.says('hi');  //undefined says hi
    14 //代码会报错,这是因为setTimeout中的this指向的是全局对象。

    为了让上面代码能够正确的运行,传统的解决方法有两种:

    1 //第一种是将this传给self,再用self来指代this
    2       says(say){
    3        var self = this;
    4        setTimeout(function(){
    5            console.log(self.type + ' says ' + say);
    6        }, 1000);
    1 //第二种方法是用bind(this)
    2       says(say){
    3        setTimeout(function(){
    4            console.log(this.type + ' says ' + say);
    5        }.bind(this), 1000);

    使用箭头函数的写法:(不会出现代码报错)

     1 class Animal {
     2     constructor(){
     3         this.type = 'animal';
     4     }
     5     says(say){
     6         setTimeout( () => {
     7             console.log(this.type + ' says ' + say);
     8         }, 1000);
     9     }
    10 }
    11  var animal = new Animal();
    12  animal.says('hi');  //animal says hi

    当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。

    4.模板字符串(用反引号来标识起始,用${}`来引用变量)

     1 //传统写法
     2 $("#result").append(
     3   "There are <b>" + basket.count + "</b> " +
     4   "items in your basket, " +
     5   "<em>" + basket.onSale +
     6   "</em> are on sale!"
     7 );
     8 
     9 //模板字符串写法
    10 $("#result").append(`
    11   There are <b>${basket.count}</b> items
    12    in your basket, <em>${basket.onSale}</em>
    13   are on sale!
    14 `);

    5.解构(按照一定模式,从数组和对象中提取值,对变量进行赋值)

     1 //传统写法
     2 let cat = 'ken';
     3 let dog = 'lili';
     4 let zoo = {cat: cat, dog: dog};
     5 console.log(zoo);  //Object {cat: "ken", dog: "lili"}
     6 
     7 //ES6解构
     8 let cat = 'ken';
     9 let dog = 'lili';
    10 let zoo = {cat, dog};
    11 console.log(zoo);  //Object {cat: "ken", dog: "lili"}
    12 
    13 //反过来也可以求一个对象的属性值
    14 let dog = {type: 'animal', many: 2};
    15 let { type, many} = dog;
    16 console.log(type, many);   //animal 2

    6.default(默认值)

    举例说明:调用animal()方法时忘了传参数

     1 //传统的做法就是加上这一句type = type || 'cat' 来指定默认值。
     2 function animal(type){
     3     type = type || 'cat';
     4     console.log(type);
     5 }
     6 animal();
     7 
     8 //ES6写法
     9 function animal(type = 'cat'){
    10     console.log(type);
    11 }
    12 animal();

    7.rest(剩余参数,是一个真的数组)&&arguments(取到全部实参,而且是一个伪数组)

    写法: ...rest(三个小圆点+rest)

    取值:除了开始参数的剩余参数,而且之后不能再取参,会报错。但是,剩余参数之前也可以没有其他参数。

    1 function func(r, ...rest) {
    2   console.log(r);
    3   console.log(rest);
    4 }
    5 func(1);//会输出:第一行:1 ; 第二行: [] 因为除了1没有其他值
    6 func(1, 2, 3, 4);//会输出:第一行:1 ; 第二行: [2,3,4]
    1 //rest前面有两个参数的情况
    2 function func(r, e, ...rest) {
    3    console.log(r,e);
    4    console.log(rest);
    5 }
    6 func(1,2);//会输出:第一行:1 2 ; 第二行: [] 
    7 func(1, 2, 3, 4);//会输出:第一行:1 2 ; 第二行: [3,4]
    1 //rest后面有参数的情况
    2 function func(r, ...rest, e) {//报错,...rest不能有后面的参数
    3    console.log(r,e);
    4    console.log(rest);
    5 }
    6 func(1,2);
    1 //rest前面没有参数
    2 function func(...rest) {
    3   console.log(rest);
    4 }
    5 func(1, 2, 3, 4);//[1,2,3,4]

    注意:(1)使用rest剩余参数后,函数的length属性会发生一些变化(不包括剩余参数)。

    1 function func(a, b, ...rest) {
    2 }
    3 console.log(func.length); // 2

    (2)arguments和剩余参数的区别:

    arguments是一个伪数组(Array-like);

    剩余参数是一个真正数组(Array),具有Array.prototype上的所有方法;

    arguments上有callee,callee上有caller;

    注:rest不能和arguments一起使用不会报错。(参考资料中显示报错,应该是之前的版本,我测试了360,Firefox都可以使用)。

    如有错误,请您指正!

    参考文档:

    30分钟掌握ES6/ES2015核心内容(上)

    ES6函数剩余参数(Rest Parameters)

  • 相关阅读:
    [ZJOI2012]灾难
    java实现风险度量
    大字段字符类型
    [CQOI2011]放棋子
    java实现还款计算
    java实现还款计算
    java实现字符串比较
    java实现字符串比较
    快速插入一百万行数据储存过程
    [六省联考2017]分手是祝愿
  • 原文地址:https://www.cnblogs.com/ksl666/p/5974176.html
Copyright © 2011-2022 走看看